service.h 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. #ifndef SERVICE_H
  2. #define SERVICE_H
  3. #include <string>
  4. #include <list>
  5. #include <vector>
  6. #include <csignal>
  7. #include <unordered_set>
  8. #include <algorithm>
  9. #include "dasynq.h"
  10. #include "dinit.h"
  11. #include "control.h"
  12. #include "service-listener.h"
  13. #include "service-constants.h"
  14. #include "load-service.h"
  15. #include "dinit-ll.h"
  16. #include "dinit-log.h"
  17. /*
  18. * This header defines service_record, a data record maintaining information about a service,
  19. * and service_set, a set of interdependent service records. It also defines some associated
  20. * types and exceptions.
  21. *
  22. * Service states
  23. * --------------
  24. * Services have both a current state and a desired state. The desired state can be
  25. * either STARTED or STOPPED. The current state can also be STARTING or STOPPING.
  26. * A service can be "pinned" in either the STARTED or STOPPED states to prevent it
  27. * from leaving that state until it is unpinned.
  28. *
  29. * The total state is a combination of the two, current and desired:
  30. * STOPPED/STOPPED : stopped and will remain stopped
  31. * STOPPED/STARTED : stopped (pinned), must be unpinned to start
  32. * STARTING/STARTED : starting, but not yet started. Dependencies may also be starting.
  33. * STARTING/STOPPED : as above, but the service will be stopped again as soon as it has
  34. * completed startup.
  35. * STARTED/STARTED : running and will continue running.
  36. * STARTED/STOPPED : started (pinned), must be unpinned to stop
  37. * STOPPING/STOPPED : stopping and will stop. Dependents may be stopping.
  38. * STOPPING/STARTED : as above, but the service will be re-started again once it stops.
  39. *
  40. * A scripted service is in the STARTING/STOPPING states during the script execution.
  41. * A process service is in the STOPPING state when it has been signalled to stop, and is
  42. * in the STARTING state when waiting for dependencies to start or for the exec() call in
  43. * the forked child to complete and return a status.
  44. *
  45. * Acquisition/release:
  46. * ------------------
  47. * Each service has a dependent-count ("required_by"). This starts at 0, adds 1 if the
  48. * service has explicitly been started (i.e. "start_explicit" is true), and adds 1 for
  49. * each dependent service which is not STOPPED (including dependents with a soft dependency).
  50. * When required_by transitions to 0, the service is stopped (unless it is pinned). When
  51. * require_by transitions from 0, the service is started (unless pinned).
  52. *
  53. * So, in general, the dependent-count determines the desired state (STARTED if the count
  54. * is greater than 0, otherwise STOPPED). However, a service can be issued a stop-and-take
  55. * down order (via `stop(true)'); this will first stop dependent services, which may restart
  56. * and cancel the stop of the former service. Finally, a service can be force-stopped, which
  57. * means that its stop process cannot be cancelled (though it may still be put in a desired
  58. * state of STARTED, meaning it will start immediately upon stopping).
  59. *
  60. * Pinning
  61. * -------
  62. * A service may be "pinned" in either STARTED or STOPPED states (or even both). Once it
  63. * reaches a pinned state, a service will not leave that state, though its desired state
  64. * may still be set. (Note that pinning prevents, but never causes, state transition).
  65. *
  66. * The priority of the different state deciders is:
  67. * - pins
  68. * - force stop flag
  69. * - desired state (which is manipulated by require/release operations)
  70. *
  71. * So a forced stop cannot occur until the service is not pinned started, for instance.
  72. *
  73. * Two-phase transition
  74. * --------------------
  75. * Transition between states occurs in two phases: propagation and execution. In both phases
  76. * a linked-list queue is used to keep track of which services need processing; this avoids
  77. * recursion (which would be of unknown depth and therefore liable to stack overflow).
  78. *
  79. * In the propagation phase, acquisition/release messages are processed, and desired state may be
  80. * altered accordingly. Start and stop requests are also propagated in this phase. The state may
  81. * be set to STARTING or STOPPING to reflect the desired state, but will never be set to STARTED
  82. * or STOPPED (that happens in the execution phase).
  83. *
  84. * The two-phase transition is needed to avoid problem where a service that becomes STOPPED has
  85. * an incorrect acquisition count, which may cause it to restart when it should not. The
  86. * propagation phase allows the acquisition count to settle before the transition to the STOPPED
  87. * state occurs, and the decision whether to restart can then be made based on the (correct)
  88. * acquisition count.
  89. *
  90. * Propagation variables:
  91. * prop_acquire: the service has transitioned to an acquired state and must issue an acquire
  92. * on its dependencies
  93. * prop_release: the service has transitioned to a released state and must issue a release on
  94. * its dependencies.
  95. *
  96. * prop_start: the service should start
  97. * prop_stop: the service should stop
  98. *
  99. * Note that "prop_acquire"/"prop_release" form a pair which cannot both be set at the same time
  100. * which is enforced via explicit checks. For "prop_start"/"prop_stop" this occurs implicitly.
  101. *
  102. * In the execution phase, actions are taken to achieve the desired state. Actual state may
  103. * transition according to the current and desired states. Processes can be sent signals, etc
  104. * in order to stop them. A process can restart if it stops, but it does so by raising prop_start
  105. * which needs to be processed in a second transition phase. Seeing as starting never causes
  106. * another process to stop, the transition-execute-transition cycle always ends at the 2nd
  107. * transition stage, at the latest.
  108. */
  109. struct service_flags_t
  110. {
  111. // on-start flags:
  112. bool rw_ready : 1; // file system should be writable once this service starts
  113. bool log_ready : 1; // syslog should be available once this service starts
  114. // Other service options flags:
  115. bool no_sigterm : 1; // do not send SIGTERM
  116. bool runs_on_console : 1; // run "in the foreground"
  117. bool starts_on_console : 1; // starts in the foreground
  118. bool shares_console : 1; // run on console, but not exclusively
  119. bool pass_cs_fd : 1; // pass this service a control socket connection via fd
  120. bool start_interruptible : 1; // the startup of this service process is ok to interrupt with SIGINT
  121. bool skippable : 1; // if interrupted the service is skipped (scripted services)
  122. bool signal_process_only : 1; // signal the session process, not the whole group
  123. service_flags_t() noexcept : rw_ready(false), log_ready(false), no_sigterm(false),
  124. runs_on_console(false), starts_on_console(false), shares_console(false),
  125. pass_cs_fd(false), start_interruptible(false), skippable(false), signal_process_only(false)
  126. {
  127. }
  128. };
  129. class service_record;
  130. class service_set;
  131. class base_process_service;
  132. /* Service dependency record */
  133. class service_dep
  134. {
  135. service_record * from;
  136. service_record * to;
  137. public:
  138. /* Whether the 'from' service is waiting for the 'to' service to start */
  139. bool waiting_on;
  140. /* Whether the 'from' service is holding an acquire on the 'to' service */
  141. bool holding_acq;
  142. const dependency_type dep_type;
  143. service_dep(service_record * from, service_record * to, dependency_type dep_type_p) noexcept
  144. : from(from), to(to), waiting_on(false), holding_acq(false), dep_type(dep_type_p)
  145. { }
  146. service_dep(const service_dep &) = delete;
  147. void operator=(const service_dep &) = delete;
  148. service_record * get_from() const noexcept
  149. {
  150. return from;
  151. }
  152. service_record * get_to() const noexcept
  153. {
  154. return to;
  155. }
  156. };
  157. /* preliminary service dependency information */
  158. class prelim_dep
  159. {
  160. public:
  161. service_record * const to;
  162. dependency_type const dep_type;
  163. prelim_dep(service_record *to_p, dependency_type dep_type_p) : to(to_p), dep_type(dep_type_p)
  164. {
  165. //
  166. }
  167. };
  168. class service_child_watcher : public eventloop_t::child_proc_watcher_impl<service_child_watcher>
  169. {
  170. public:
  171. base_process_service * service;
  172. dasynq::rearm status_change(eventloop_t &eloop, pid_t child, int status) noexcept;
  173. service_child_watcher(base_process_service * sr) noexcept : service(sr) { }
  174. service_child_watcher(const service_child_watcher &) = delete;
  175. void operator=(const service_child_watcher &) = delete;
  176. };
  177. // Watcher for the pipe used to receive exec() failure status errno
  178. class exec_status_pipe_watcher : public eventloop_t::fd_watcher_impl<exec_status_pipe_watcher>
  179. {
  180. public:
  181. base_process_service * service;
  182. dasynq::rearm fd_event(eventloop_t &eloop, int fd, int flags) noexcept;
  183. exec_status_pipe_watcher(base_process_service * sr) noexcept : service(sr) { }
  184. exec_status_pipe_watcher(const exec_status_pipe_watcher &) = delete;
  185. void operator=(exec_status_pipe_watcher &) = delete;
  186. };
  187. // service_record: base class for service record containing static information
  188. // and current state of each service.
  189. //
  190. // This abstract base class defines the dependency behaviour of services. The actions to actually bring a
  191. // service up or down are specified by subclasses in the virtual methods (see especially bring_up() and
  192. // bring_down()).
  193. //
  194. class service_record
  195. {
  196. protected:
  197. using string = std::string;
  198. using time_val = dasynq::time_val;
  199. private:
  200. string service_name;
  201. service_type_t record_type; // service_type_t::DUMMY, PROCESS, SCRIPTED, or INTERNAL
  202. // 'service_state' can be any valid state: STARTED, STARTING, STOPPING, STOPPED.
  203. // 'desired_state' is only set to final states: STARTED or STOPPED.
  204. service_state_t service_state = service_state_t::STOPPED;
  205. service_state_t desired_state = service_state_t::STOPPED;
  206. protected:
  207. string pid_file;
  208. service_flags_t onstart_flags;
  209. string logfile; // log file name, empty string specifies /dev/null
  210. bool auto_restart : 1; // whether to restart this (process) if it dies unexpectedly
  211. bool smooth_recovery : 1; // whether the service process can restart without bringing down service
  212. bool pinned_stopped : 1;
  213. bool pinned_started : 1;
  214. bool waiting_for_deps : 1; // if STARTING, whether we are waiting for dependencies/console
  215. // if STOPPING, whether we are waiting for dependents to stop
  216. bool waiting_for_console : 1; // waiting for exclusive console access (while STARTING)
  217. bool have_console : 1; // whether we have exclusive console access (STARTING/STARTED)
  218. bool waiting_for_execstat : 1; // if we are waiting for exec status after fork()
  219. bool start_explicit : 1; // whether we are are explicitly required to be started
  220. bool prop_require : 1; // require must be propagated
  221. bool prop_release : 1; // release must be propagated
  222. bool prop_failure : 1; // failure to start must be propagated
  223. bool prop_start : 1;
  224. bool prop_stop : 1;
  225. bool restarting : 1; // re-starting after unexpected termination
  226. bool start_failed : 1; // failed to start (reset when begins starting)
  227. bool start_skipped : 1; // start was skipped by interrupt
  228. int required_by = 0; // number of dependents wanting this service to be started
  229. // list of dependencies
  230. typedef std::list<service_dep> dep_list;
  231. // list of dependents
  232. typedef std::list<service_dep *> dpt_list;
  233. dep_list depends_on; // services this one depends on
  234. dpt_list dependents; // services depending on this one
  235. service_set *services; // the set this service belongs to
  236. std::unordered_set<service_listener *> listeners;
  237. // Process services:
  238. bool force_stop; // true if the service must actually stop. This is the
  239. // case if for example the process dies; the service,
  240. // and all its dependencies, MUST be stopped.
  241. int term_signal = -1; // signal to use for process termination
  242. string socket_path; // path to the socket for socket-activation service
  243. int socket_perms; // socket permissions ("mode")
  244. uid_t socket_uid = -1; // socket user id or -1
  245. gid_t socket_gid = -1; // socket group id or -1
  246. stopped_reason_t stop_reason = stopped_reason_t::NORMAL; // reason why stopped
  247. string start_on_completion; // service to start when this one completes
  248. // Data for use by service_set
  249. public:
  250. // Console queue.
  251. lld_node<service_record> console_queue_node;
  252. // Propagation and start/stop queues
  253. lls_node<service_record> prop_queue_node;
  254. lls_node<service_record> stop_queue_node;
  255. protected:
  256. // Service has actually stopped (includes having all dependents
  257. // reaching STOPPED state).
  258. void stopped() noexcept;
  259. // Service has successfully started
  260. void started() noexcept;
  261. // Service failed to start (only called when in STARTING state).
  262. // dep_failed: whether failure is recorded due to a dependency failing
  263. // immediate_stop: whether to set state as STOPPED and handle complete stop.
  264. void failed_to_start(bool dep_failed = false, bool immediate_stop = true) noexcept;
  265. // Run a child process (call after forking).
  266. // - args specifies the program arguments including the executable (argv[0])
  267. // - working_dir specifies the working directory; may be null
  268. // - logfile specifies the logfile
  269. // - on_console: if true, process is run with access to console
  270. // - wpipefd: if the exec is unsuccessful, or another error occurs beforehand, the
  271. // error number (errno) is written to this file descriptor
  272. // - csfd: the control socket fd; may be -1 to inhibit passing of control socket
  273. // - socket_fd: the pre-opened socket file descriptor (may be -1)
  274. // - uid/gid: the identity to run the process as (may be both -1, otherwise both must be valid)
  275. void run_child_proc(const char * const *args, const char *working_dir, const char *logfile,
  276. bool on_console, int wpipefd, int csfd, int socket_fd, uid_t uid, gid_t gid) noexcept;
  277. // A dependency has reached STARTED state
  278. void dependency_started() noexcept;
  279. void all_deps_started() noexcept;
  280. // Start all dependencies, return true if all have started
  281. bool start_check_dependencies() noexcept;
  282. // Check whether all dependencies have started (i.e. whether we can start now)
  283. bool check_deps_started() noexcept;
  284. // Whether a STOPPING service can immediately transition to STARTED.
  285. bool can_interrupt_stop() noexcept
  286. {
  287. return waiting_for_deps && ! force_stop;
  288. }
  289. // A dependent has reached STOPPED state
  290. void dependent_stopped() noexcept;
  291. // check if all dependents have stopped
  292. bool stop_check_dependents() noexcept;
  293. // issue a stop to all dependents, return true if they are all already stopped
  294. bool stop_dependents() noexcept;
  295. void require() noexcept;
  296. void release(bool issue_stop = true) noexcept;
  297. void release_dependencies() noexcept;
  298. // Check if service is, fundamentally, stopped.
  299. bool is_stopped() noexcept
  300. {
  301. return service_state == service_state_t::STOPPED
  302. || (service_state == service_state_t::STARTING && waiting_for_deps);
  303. }
  304. void notify_listeners(service_event_t event) noexcept
  305. {
  306. for (auto l : listeners) {
  307. l->service_event(this, event);
  308. }
  309. }
  310. // Queue to run on the console. 'acquired_console()' will be called when the console is available.
  311. // Has no effect if the service has already queued for console.
  312. void queue_for_console() noexcept;
  313. // Release console (console must be currently held by this service)
  314. void release_console() noexcept;
  315. bool do_auto_restart() noexcept;
  316. // Started state reached
  317. bool process_started() noexcept;
  318. // Called on transition of desired state from stopped to started (or unpinned stop)
  319. void do_start() noexcept;
  320. // Begin stopping, release activation.
  321. void do_stop() noexcept;
  322. // Set the service state
  323. void set_state(service_state_t new_state) noexcept
  324. {
  325. service_state = new_state;
  326. }
  327. // Virtual functions, to be implemented by service implementations:
  328. // Do any post-dependency startup; return false on failure
  329. virtual bool bring_up() noexcept;
  330. // All dependents have stopped, and this service should proceed to stop.
  331. virtual void bring_down() noexcept;
  332. // Whether a STARTING service can immediately transition to STOPPED (as opposed to
  333. // having to wait for it reach STARTED and then go through STOPPING).
  334. virtual bool can_interrupt_start() noexcept
  335. {
  336. return waiting_for_deps;
  337. }
  338. // Whether a STARTING service can transition to its STARTED state, once all
  339. // dependencies have started.
  340. virtual bool can_proceed_to_start() noexcept
  341. {
  342. return true;
  343. }
  344. // Interrupt startup. Returns true if service start is fully cancelled; returns false if cancel order
  345. // issued but service has not yet responded (state will be set to STOPPING).
  346. virtual bool interrupt_start() noexcept;
  347. // The service is becoming inactive - i.e. it has stopped and will not be immediately restarted. Perform
  348. // any appropriate cleanup.
  349. virtual void becoming_inactive() noexcept { }
  350. public:
  351. service_record(service_set *set, string name)
  352. : service_name(name), service_state(service_state_t::STOPPED),
  353. desired_state(service_state_t::STOPPED), auto_restart(false), smooth_recovery(false),
  354. pinned_stopped(false), pinned_started(false), waiting_for_deps(false),
  355. waiting_for_console(false), have_console(false), waiting_for_execstat(false),
  356. start_explicit(false), prop_require(false), prop_release(false), prop_failure(false),
  357. prop_start(false), prop_stop(false), restarting(false), start_failed(false),
  358. start_skipped(false), force_stop(false)
  359. {
  360. services = set;
  361. record_type = service_type_t::DUMMY;
  362. socket_perms = 0;
  363. }
  364. service_record(service_set *set, string name, service_type_t record_type_p,
  365. const std::list<prelim_dep> &deplist_p)
  366. : service_record(set, name)
  367. {
  368. services = set;
  369. service_name = name;
  370. this->record_type = record_type_p;
  371. try {
  372. for (auto & pdep : deplist_p) {
  373. auto b = depends_on.emplace(depends_on.end(), this, pdep.to, pdep.dep_type);
  374. try {
  375. pdep.to->dependents.push_back(&(*b));
  376. }
  377. catch (...) {
  378. // we'll roll back one now and re-throw:
  379. depends_on.pop_back();
  380. throw;
  381. }
  382. }
  383. }
  384. catch (...) {
  385. for (auto & dep : depends_on) {
  386. dep.get_to()->dependents.pop_back();
  387. }
  388. throw;
  389. }
  390. }
  391. service_record(const service_record &) = delete;
  392. void operator=(const service_record &) = delete;
  393. virtual ~service_record() noexcept
  394. {
  395. }
  396. // Get the type of this service record
  397. service_type_t get_type() noexcept
  398. {
  399. return record_type;
  400. }
  401. // begin transition from stopped to started state or vice versa depending on current and desired state
  402. void execute_transition() noexcept;
  403. void do_propagation() noexcept;
  404. // Console is available.
  405. void acquired_console() noexcept;
  406. // Get the target (aka desired) state.
  407. service_state_t get_target_state() noexcept
  408. {
  409. return desired_state;
  410. }
  411. // Set logfile, should be done before service is started
  412. void set_log_file(string logfile)
  413. {
  414. this->logfile = logfile;
  415. }
  416. // Set whether this service should automatically restart when it dies
  417. void set_auto_restart(bool auto_restart) noexcept
  418. {
  419. this->auto_restart = auto_restart;
  420. }
  421. void set_smooth_recovery(bool smooth_recovery) noexcept
  422. {
  423. this->smooth_recovery = smooth_recovery;
  424. }
  425. // Set "on start" flags (commands)
  426. void set_flags(service_flags_t flags) noexcept
  427. {
  428. this->onstart_flags = flags;
  429. }
  430. void set_pid_file(string &&pid_file) noexcept
  431. {
  432. this->pid_file = std::move(pid_file);
  433. }
  434. void set_socket_details(string &&socket_path, int socket_perms, uid_t socket_uid, uid_t socket_gid)
  435. noexcept
  436. {
  437. this->socket_path = std::move(socket_path);
  438. this->socket_perms = socket_perms;
  439. this->socket_uid = socket_uid;
  440. this->socket_gid = socket_gid;
  441. }
  442. // Set the service that this one "chains" to. When this service completes, the named service is started.
  443. void set_chain_to(string &&chain_to)
  444. {
  445. start_on_completion = std::move(chain_to);
  446. }
  447. const std::string &get_name() const noexcept { return service_name; }
  448. service_state_t get_state() const noexcept { return service_state; }
  449. void start(bool activate = true) noexcept; // start the service
  450. void stop(bool bring_down = true) noexcept; // stop the service
  451. void forced_stop() noexcept; // force-stop this service and all dependents
  452. // Pin the service in "started" state (when it reaches the state)
  453. void pin_start() noexcept
  454. {
  455. pinned_started = true;
  456. }
  457. // Pin the service in "stopped" state (when it reaches the state)
  458. void pin_stop() noexcept
  459. {
  460. pinned_stopped = true;
  461. }
  462. // Remove both "started" and "stopped" pins. If the service is currently pinned
  463. // in either state but would naturally be in the opposite state, it will immediately
  464. // commence starting/stopping.
  465. void unpin() noexcept;
  466. // Is this a dummy service (used only when loading a new service)?
  467. bool is_dummy() noexcept
  468. {
  469. return record_type == service_type_t::DUMMY;
  470. }
  471. bool did_start_fail() noexcept
  472. {
  473. return start_failed;
  474. }
  475. bool was_start_skipped() noexcept
  476. {
  477. return start_skipped;
  478. }
  479. // Add a listener. A listener must only be added once. May throw std::bad_alloc.
  480. void add_listener(service_listener * listener)
  481. {
  482. listeners.insert(listener);
  483. }
  484. // Remove a listener.
  485. void remove_listener(service_listener * listener) noexcept
  486. {
  487. listeners.erase(listener);
  488. }
  489. // Assuming there is one reference (from a control link), return true if this is the only reference,
  490. // or false if there are others (including dependents).
  491. bool has_lone_ref() noexcept
  492. {
  493. if (! dependents.empty()) return false;
  494. auto i = listeners.begin();
  495. return (++i == listeners.end());
  496. }
  497. // Prepare this service to be unloaded.
  498. void prepare_for_unload() noexcept
  499. {
  500. // Remove all dependencies:
  501. for (auto &dep : depends_on) {
  502. auto &dep_dpts = dep.get_to()->dependents;
  503. dep_dpts.erase(std::find(dep_dpts.begin(), dep_dpts.end(), &dep));
  504. }
  505. depends_on.clear();
  506. }
  507. // Why did the service stop?
  508. stopped_reason_t get_stop_reason()
  509. {
  510. return stop_reason;
  511. }
  512. bool is_waiting_for_console()
  513. {
  514. return waiting_for_console;
  515. }
  516. bool has_console()
  517. {
  518. return have_console;
  519. }
  520. virtual pid_t get_pid()
  521. {
  522. return -1;
  523. }
  524. virtual int get_exit_status()
  525. {
  526. return 0;
  527. }
  528. dep_list & get_dependencies()
  529. {
  530. return depends_on;
  531. }
  532. // Add a dependency. Caller must ensure that the services are in an appropriate state and that
  533. // a circular dependency chain is not created. Propagation queues should be processed after
  534. // calling this. May throw std::bad_alloc.
  535. service_dep & add_dep(service_record *to, dependency_type dep_type)
  536. {
  537. depends_on.emplace_back(this, to, dep_type);
  538. try {
  539. to->dependents.push_back(& depends_on.back());
  540. }
  541. catch (...) {
  542. depends_on.pop_back();
  543. throw;
  544. }
  545. if (dep_type == dependency_type::REGULAR) {
  546. if (service_state == service_state_t::STARTING || service_state == service_state_t::STARTED) {
  547. to->require();
  548. depends_on.back().holding_acq = true;
  549. }
  550. }
  551. return depends_on.back();
  552. }
  553. // Remove a dependency, of the given type, to the given service. Propagation queues should be processed
  554. // after calling.
  555. void rm_dep(service_record *to, dependency_type dep_type) noexcept
  556. {
  557. for (auto i = depends_on.begin(); i != depends_on.end(); i++) {
  558. auto & dep = *i;
  559. if (dep.get_to() == to && dep.dep_type == dep_type) {
  560. for (auto j = to->dependents.begin(); ; j++) {
  561. if (*j == &dep) {
  562. to->dependents.erase(j);
  563. break;
  564. }
  565. }
  566. if (dep.holding_acq) {
  567. to->release();
  568. }
  569. depends_on.erase(i);
  570. break;
  571. }
  572. }
  573. }
  574. // Start a speficic dependency of this service. Should only be called if this service is in an
  575. // appropriate state (started, starting). The dependency is marked as holding acquired; when
  576. // this service stops, the dependency will be released and may also stop.
  577. void start_dep(service_dep &dep)
  578. {
  579. if (! dep.holding_acq) {
  580. dep.get_to()->require();
  581. dep.holding_acq = true;
  582. }
  583. }
  584. };
  585. inline auto extract_prop_queue(service_record *sr) -> decltype(sr->prop_queue_node) &
  586. {
  587. return sr->prop_queue_node;
  588. }
  589. inline auto extract_stop_queue(service_record *sr) -> decltype(sr->stop_queue_node) &
  590. {
  591. return sr->stop_queue_node;
  592. }
  593. inline auto extract_console_queue(service_record *sr) -> decltype(sr->console_queue_node) &
  594. {
  595. return sr->console_queue_node;
  596. }
  597. /*
  598. * A service_set, as the name suggests, manages a set of services.
  599. *
  600. * Other than the ability to find services by name, the service set manages various queues.
  601. * One is the queue for processes wishing to acquire the console. There is also a set of
  602. * processes that want to start, and another set of those that want to stop. These latter
  603. * two "queues" (not really queues since their order is not important) are used to prevent too
  604. * much recursion and to prevent service states from "bouncing" too rapidly.
  605. *
  606. * A service that wishes to start or stop puts itself on the start/stop queue; a service that
  607. * needs to propagate changes to dependent services or dependencies puts itself on the
  608. * propagation queue. Any operation that potentially manipulates the queues must be followed
  609. * by a "process queues" order (processQueues() method).
  610. *
  611. * Note that processQueues always repeatedly processes both queues until they are empty. The
  612. * process is finite because starting a service can never cause services to stop, unless they
  613. * fail to start, which should cause them to stop semi-permanently.
  614. */
  615. class service_set
  616. {
  617. protected:
  618. int active_services;
  619. std::list<service_record *> records;
  620. bool restart_enabled; // whether automatic restart is enabled (allowed)
  621. shutdown_type_t shutdown_type = shutdown_type_t::CONTINUE; // Shutdown type, if stopping
  622. // Services waiting for exclusive access to the console
  623. dlist<service_record, extract_console_queue> console_queue;
  624. // Propagation and start/stop "queues" - list of services waiting for processing
  625. slist<service_record, extract_prop_queue> prop_queue;
  626. slist<service_record, extract_stop_queue> stop_queue;
  627. public:
  628. service_set()
  629. {
  630. active_services = 0;
  631. restart_enabled = true;
  632. }
  633. virtual ~service_set()
  634. {
  635. for (auto * s : records) {
  636. delete s;
  637. }
  638. }
  639. // Start the specified service. The service will be marked active.
  640. void start_service(service_record *svc)
  641. {
  642. svc->start();
  643. process_queues();
  644. }
  645. // Stop the specified service. Its active mark will be cleared.
  646. void stop_service(service_record *svc)
  647. {
  648. svc->stop(true);
  649. process_queues();
  650. }
  651. // Locate an existing service record.
  652. service_record *find_service(const std::string &name) noexcept;
  653. // Load a service description, and dependencies, if there is no existing
  654. // record for the given name.
  655. // Throws:
  656. // service_load_exc (or subclass) on problem with service description
  657. // std::bad_alloc on out-of-memory condition
  658. virtual service_record *load_service(const char *name)
  659. {
  660. auto r = find_service(name);
  661. if (r == nullptr) {
  662. throw service_not_found(name);
  663. }
  664. return r;
  665. }
  666. // Start the service with the given name. The named service will begin
  667. // transition to the 'started' state.
  668. //
  669. // Throws a service_load_exc (or subclass) if the service description
  670. // cannot be loaded or is invalid;
  671. // Throws std::bad_alloc if out of memory.
  672. void start_service(const char *name)
  673. {
  674. using namespace std;
  675. service_record *record = load_service(name);
  676. service_set::start_service(record);
  677. }
  678. void add_service(service_record *svc)
  679. {
  680. records.push_back(svc);
  681. }
  682. void remove_service(service_record *svc)
  683. {
  684. records.erase(std::find(records.begin(), records.end(), svc));
  685. }
  686. // Get the list of all loaded services.
  687. const std::list<service_record *> &list_services() noexcept
  688. {
  689. return records;
  690. }
  691. // Stop the service with the given name. The named service will begin
  692. // transition to the 'stopped' state.
  693. void stop_service(const std::string &name) noexcept;
  694. // Add a service record to the state propagation queue. The service record will have its
  695. // do_propagation() method called when the queue is processed.
  696. void add_prop_queue(service_record *service) noexcept
  697. {
  698. if (! prop_queue.is_queued(service)) {
  699. prop_queue.insert(service);
  700. }
  701. }
  702. // Add a service record to the stop queue. The service record will have its
  703. // execute_transition() method called when the queue is processed.
  704. void add_transition_queue(service_record *service) noexcept
  705. {
  706. if (! stop_queue.is_queued(service)) {
  707. stop_queue.insert(service);
  708. }
  709. }
  710. // Process state propagation and start/stop queues, until they are empty.
  711. void process_queues() noexcept
  712. {
  713. while (! stop_queue.is_empty() || ! prop_queue.is_empty()) {
  714. while (! prop_queue.is_empty()) {
  715. auto next = prop_queue.pop_front();
  716. next->do_propagation();
  717. }
  718. while (! stop_queue.is_empty()) {
  719. auto next = stop_queue.pop_front();
  720. next->execute_transition();
  721. }
  722. }
  723. }
  724. // Set the console queue tail (returns previous tail)
  725. void append_console_queue(service_record * newTail) noexcept
  726. {
  727. bool was_empty = console_queue.is_empty();
  728. console_queue.append(newTail);
  729. if (was_empty) {
  730. enable_console_log(false);
  731. }
  732. }
  733. // Pull and dispatch a waiter from the console queue
  734. void pull_console_queue() noexcept
  735. {
  736. if (console_queue.is_empty()) {
  737. enable_console_log(true);
  738. }
  739. else {
  740. service_record * front = console_queue.pop_front();
  741. front->acquired_console();
  742. }
  743. }
  744. void unqueue_console(service_record * service) noexcept
  745. {
  746. if (console_queue.is_queued(service)) {
  747. console_queue.unlink(service);
  748. }
  749. }
  750. // Check if console queue is empty (possibly due to console already having
  751. // been assigned to the only queueing service)
  752. bool is_console_queue_empty() noexcept
  753. {
  754. return console_queue.is_empty();
  755. }
  756. // Check whether a service is queued for the console
  757. bool is_queued_for_console(service_record * service) noexcept
  758. {
  759. return console_queue.is_queued(service);
  760. }
  761. // Notification from service that it is active (state != STOPPED)
  762. // Only to be called on the transition from inactive to active.
  763. void service_active(service_record *) noexcept;
  764. // Notification from service that it is inactive (STOPPED)
  765. // Only to be called on the transition from active to inactive.
  766. void service_inactive(service_record *) noexcept;
  767. // Find out how many services are active (starting, running or stopping,
  768. // but not stopped).
  769. int count_active_services() noexcept
  770. {
  771. return active_services;
  772. }
  773. void stop_all_services(shutdown_type_t type = shutdown_type_t::HALT) noexcept
  774. {
  775. restart_enabled = false;
  776. shutdown_type = type;
  777. for (std::list<service_record *>::iterator i = records.begin(); i != records.end(); ++i) {
  778. (*i)->stop(false);
  779. (*i)->unpin();
  780. }
  781. process_queues();
  782. }
  783. void set_auto_restart(bool restart) noexcept
  784. {
  785. restart_enabled = restart;
  786. }
  787. bool get_auto_restart() noexcept
  788. {
  789. return restart_enabled;
  790. }
  791. shutdown_type_t get_shutdown_type() noexcept
  792. {
  793. return shutdown_type;
  794. }
  795. // Get an identifier for the run-time type of the service set (similar to typeid, but without
  796. // requiring RTTI to be enabled during compilation).
  797. virtual int get_set_type_id()
  798. {
  799. return SSET_TYPE_NONE;
  800. }
  801. };
  802. // A service directory entry, tracking the directory as a nul-terminated string, which may either
  803. // be static or dynamically allocated (via new char[...]).
  804. class service_dir_entry
  805. {
  806. const char *dir;
  807. bool dir_dyn_allocd; // dynamically allocated?
  808. public:
  809. service_dir_entry(const char *dir_p, bool dir_dyn_allocd_p) :
  810. dir(dir_p), dir_dyn_allocd(dir_dyn_allocd_p)
  811. { }
  812. ~service_dir_entry()
  813. {
  814. if (dir_dyn_allocd) {
  815. delete[] dir;
  816. }
  817. }
  818. const char *get_dir() const
  819. {
  820. return dir;
  821. }
  822. };
  823. // A service set which loads services from one of several service directories.
  824. class dirload_service_set : public service_set
  825. {
  826. std::vector<service_dir_entry> service_dirs; // directories containing service descriptions
  827. public:
  828. dirload_service_set() : service_set()
  829. {
  830. // nothing to do.
  831. }
  832. dirload_service_set(const dirload_service_set &) = delete;
  833. // Construct a dirload_service_set which loads services from the specified directory. The
  834. // directory specified can be dynamically allocated via "new char[...]" (dyn_allocd == true)
  835. // or statically allocated.
  836. dirload_service_set(const char *service_dir_p, bool dyn_allocd = false) : service_set()
  837. {
  838. service_dirs.emplace_back(service_dir_p, dyn_allocd);
  839. }
  840. // Append a directory to the list of service directories, so that it is searched last for
  841. // service description files.
  842. void add_service_dir(const char *service_dir_p, bool dyn_allocd = true)
  843. {
  844. service_dirs.emplace_back(service_dir_p, dyn_allocd);
  845. }
  846. int get_service_dir_count()
  847. {
  848. return service_dirs.size();
  849. }
  850. const char * get_service_dir(int n)
  851. {
  852. return service_dirs[n].get_dir();
  853. }
  854. service_record *load_service(const char *name) override;
  855. int get_set_type_id() override
  856. {
  857. return SSET_TYPE_DIRLOAD;
  858. }
  859. };
  860. #endif