libprocess.dox 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. /**
  7. @page libprocess libkea-process - Controllable Process Layer (CPL)
  8. @section cpl Controllable Process Layer (CPL)
  9. During the design and development of D2 (Kea's DHCP-DDNS process), an abstract
  10. layer for process control, called the Controllable Process Layer or CPL, was
  11. created. Kea's DHCP servers were initially developed prior to D2 and thus
  12. before CPL existed.
  13. Out of short term convenience and the fact that only D2 was using it, the CPL
  14. was initially developed as part of D2 in src/bin/d2. In order to use CPL for
  15. new Kea processes, it has since been moved into its own library, libkea-process.
  16. The following sections describe the architecture of CPL and how it can be used to implement new daemons in Kea.
  17. The CPL provides the essentials for a controllable, configurable,
  18. asynchronous process. They are the result of an effort to distill the
  19. common facets of process control currently duplicated in Kea's
  20. DHCP servers into a reusable construct. The classes which form this abstract
  21. base are shown in the following class diagram:
  22. @image html abstract_app_classes.svg "Controllable Process Layer Classes"
  23. - isc::process::DControllerBase - provides all of the services necessary to manage
  24. an application process class derived from isc::d2::DProcess. These services include:
  25. - Command line argument handling
  26. - Process instantiation and initialization
  27. - Support for stand-alone execution
  28. - Process event loop invocation and shutdown
  29. It creates and manages an instance of isc::process::DProcessBase. The CPL is
  30. designed for asynchronous event processing applications. It is constructed
  31. to use ASIO library for IO processing. @c DControllerBase owns an
  32. isc::asiolink::IOService instance and it passes this into the @c
  33. DProcessBase constructor. It is this @c IOService that is used to drive the
  34. process's event loop. The controller is designed to provide any interfaces
  35. between the process it controls and the outside world.
  36. @c DControllerBase provides configuration for its process via a JSON file
  37. specified as a mandatory command line argument. The file structure is
  38. expected be as follows:
  39. { "<module-name>": {<module-config>} }
  40. where:
  41. - module-name : is a label which uniquely identifies the
  42. configuration data for the (i.e. the controlled process.)
  43. It is the value returned by @ref
  44. isc::process::DControllerBase::getAppName()
  45. - module-config: a set of zero or more JSON elements which comprise
  46. application's configuration values. Element syntax is governed
  47. by those elements supported in isc::cc.
  48. The file may contain an arbitrary number of other modules.
  49. @todo Eventually, some sort of secure socket interface which supports remote
  50. control operations such as configuration changes or status reporting will
  51. likely be implemented.
  52. - isc::process::DProcessBase - defines an asynchronous-event processor (i.e.
  53. application) which provides a uniform interface to:
  54. - Instantiate and initialize a process instance
  55. - "Run" the application by starting its event loop
  56. - Inject events to control the process
  57. It owns an instance of @c DCfgMgrBase.
  58. - isc::process::DCfgMgrBase - provides the mechanisms for managing an application's
  59. configuration. This includes services for parsing sets of configuration
  60. values, storing the parsed information in its converted form, and retrieving
  61. the information on demand. It owns an instance of @c DCfgContextBase, which
  62. provides a "global" context for information that is accessible before, during,
  63. and after parsing.
  64. - isc::process::DCfgContextBase - implements a container for configuration
  65. information or "context". It provides a single enclosure for the storage of
  66. configuration parameters or any other information that needs to accessible
  67. within a given context.
  68. The following sequence diagram shows how a configuration from file moves
  69. through the CPL layer:
  70. @image html config_from_file_sequence.svg "CPL Configuration From File Sequence"
  71. The CPL classes will likely move into a common library.
  72. @section cplSignals CPL Signal Handling
  73. CPL supports interaction with the outside world via OS signals. The default
  74. implementation supports the following signal driven behavior:
  75. - SIGHUP receipt of this signal will cause a reloading of the configuration
  76. file.
  77. - SIGINT/SIGTERM receipt of either of these signals will initiate an
  78. orderly shutdown.
  79. CPL applications wait for for process asynchronous IO events through
  80. isc::asiolink::IOService::run() or its variants. These calls are not
  81. interrupted upon signal receipt as is the select() function and while
  82. boost::asio provides a signal mechanism it requires linking in additional
  83. libraries. Therefore, CPL provides its own signal handling mechanism to
  84. propagate an OS signal such as SIGHUP to an IOService as a ready event with a
  85. callback.
  86. isc::process::DControllerBase uses two mechanisms to carry out signal handling. It
  87. uses isc::util::SignalSet to catch OS signals, and isc::process::IOSignalQueue to
  88. propagate them to its isc::asiolink::IOService as instances of
  89. isc::process::IOSignal.
  90. This CPL signaling class hierarchy is illustrated in the following diagram:
  91. @image html cpl_signal_classes.svg "CPL Signal Classes"
  92. The mechanics of isc::process::IOSignal are straight forward. Upon construction it
  93. is given the target isc::asiolink::IOService, the value of the OS signal to
  94. send (e.g. SIGINT, SIGHUP...), and an isc::process::IOSignalHandler. This handler
  95. should contain the logic the caller would normally execute in its OS signal
  96. handler. Each isc::process::IOSignal instance has a unique identifier called its
  97. sequence_id.
  98. Internally, IOSignal creates a 1 ms, one-shot timer, on the given
  99. IOService. When the timer expires its event handler invokes the caller's
  100. IOSignalHandler passing it the sequence_id of the IOSignal.
  101. Sending IOSignals is done through an isc::process::IOSignalQueue. This class is
  102. used to create the signals, house them until they are delivered, and dequeue
  103. them so they can be been handled. To generate an IOSignal when an OS signal
  104. arrives, the process's OS signal handler need only call
  105. isc::process::IOSignalQueue::pushSignal() with the appropriate values.
  106. To dequeue the IOSignal inside the caller's IOSignalHandler, one simply
  107. invokes isc::process::IOSignalQueue::popSignal() passing it the sequence_id
  108. parameter passed to the handler. This method returns a pointer to
  109. instigating IOSignal from which the value of OS signal (i.e. SIGINT,
  110. SIGUSR1...) can be obtained. Note that calling popSignal() removes the
  111. IOSignalPtr from the queue, which should reduce its reference count to
  112. zero upon exiting the handler (unless a deliberate copy of it is made).
  113. A typical isc::process::IOSignalHandler might be structured as follows:
  114. @code
  115. void processSignal(IOSignalId sequence_id) {
  116. // Pop the signal instance off the queue.
  117. IOSignalPtr signal = io_signal_queue_->popSignal(sequence_id);
  118. int os_signal_value = signal->getSignum();
  119. :
  120. // logic based on the signal value
  121. :
  122. }
  123. @endcode
  124. IOSignal's handler invocation code will catch, log ,and then swallow any
  125. exceptions thrown by an IOSignalHandler. This is done to protect the integrity
  126. IOService context.
  127. CPL integrates the use of the two mechanisms by registering the method,
  128. isc::process::DControllerBase::osSignalHandler(), as the
  129. isc::util::SignalSet::onreceipt_handler_. This configures SignalSet's internal
  130. handler to invoke the method each time a signal arrives. When invoked, this
  131. method will call isc::process::IOSignalQueue::pushSignal() to create an
  132. isc::process::IOSignal, passing in the OS signal received and
  133. isc::process::DControllerBase::ioSignalHandler() to use as the IOSignal's
  134. ready event handler
  135. The following sequence diagram depicts the initialization of signal handling
  136. during startup and the subsequent receipt of a SIGHUP:
  137. @image html cpl_signal_sequence.svg "CPL Signal Handling Sequence"
  138. */