proc-service.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. #include <cstring>
  2. #include <type_traits>
  3. #include <sys/un.h>
  4. #include <sys/socket.h>
  5. #include "dinit.h"
  6. #include "dinit-socket.h"
  7. #include "dinit-util.h"
  8. #include "dinit-log.h"
  9. #include "proc-service.h"
  10. /*
  11. * Most of the implementation for process-based services (process, scripted, bgprocess) is here.
  12. *
  13. * See proc-service.h header for interface details.
  14. */
  15. // Given a string and a list of pairs of (start,end) indices for each argument in that string,
  16. // store a null terminator for the argument. Return a `char *` vector containing the beginning
  17. // of each argument and a trailing nullptr. (The returned array is invalidated if the string is
  18. // later modified).
  19. std::vector<const char *> separate_args(std::string &s,
  20. const std::list<std::pair<unsigned,unsigned>> &arg_indices)
  21. {
  22. std::vector<const char *> r;
  23. r.reserve(arg_indices.size() + 1);
  24. // First store nul terminator for each part:
  25. for (auto index_pair : arg_indices) {
  26. if (index_pair.second < s.length()) {
  27. s[index_pair.second] = 0;
  28. }
  29. }
  30. // Now we can get the C string (c_str) and store offsets into it:
  31. const char * cstr = s.c_str();
  32. for (auto index_pair : arg_indices) {
  33. r.push_back(cstr + index_pair.first);
  34. }
  35. r.push_back(nullptr);
  36. return r;
  37. }
  38. void process_service::exec_succeeded() noexcept
  39. {
  40. // This could be a smooth recovery (state already STARTED). Even more, the process
  41. // might be stopped (and killed via a signal) during smooth recovery. We don't to
  42. // process startup again in either case, so we check for state STARTING:
  43. if (get_state() == service_state_t::STARTING) {
  44. if (force_notification_fd != -1 || !notification_var.empty()) {
  45. // Wait for readiness notification:
  46. readiness_watcher.set_enabled(event_loop, true);
  47. }
  48. else {
  49. if (waiting_stopstart_timer) {
  50. process_timer.stop_timer(event_loop);
  51. waiting_stopstart_timer = false;
  52. }
  53. started();
  54. }
  55. }
  56. else if (get_state() == service_state_t::STOPPING) {
  57. // stopping, but smooth recovery was in process. That's now over so we can
  58. // commence normal stop. Note that if pid == -1 the process already stopped,
  59. // that is correctly handled by bring_down().
  60. if (stop_check_dependents()) {
  61. bring_down();
  62. }
  63. }
  64. }
  65. void scripted_service::exec_succeeded() noexcept
  66. {
  67. // For a scripted service, this means nothing other than that the start/stop
  68. // script will now begin.
  69. }
  70. rearm exec_status_pipe_watcher::fd_event(eventloop_t &loop, int fd, int flags) noexcept
  71. {
  72. base_process_service *sr = service;
  73. sr->waiting_for_execstat = false;
  74. run_proc_err exec_status;
  75. int r = read(get_watched_fd(), &exec_status, sizeof(exec_status));
  76. deregister(loop);
  77. close(get_watched_fd());
  78. if (r > 0) {
  79. // We read an errno code; exec() failed, and the service startup failed.
  80. if (sr->pid != -1) {
  81. sr->child_listener.deregister(event_loop, sr->pid);
  82. sr->reserved_child_watch = false;
  83. if (sr->waiting_stopstart_timer) {
  84. sr->process_timer.stop_timer(loop);
  85. sr->waiting_stopstart_timer = false;
  86. }
  87. }
  88. sr->pid = -1;
  89. sr->exec_failed(exec_status);
  90. }
  91. else {
  92. sr->exec_succeeded();
  93. if (sr->pid == -1) {
  94. // Somehow the process managed to complete before we even saw the exec() status.
  95. sr->handle_exit_status(sr->exit_status);
  96. }
  97. }
  98. sr->services->process_queues();
  99. return rearm::REMOVED;
  100. }
  101. rearm ready_notify_watcher::fd_event(eventloop_t &, int fd, int flags) noexcept
  102. {
  103. char buf[128];
  104. if (service->get_state() == service_state_t::STARTING) {
  105. // can we actually read anything from the notification pipe?
  106. int r = bp_sys::read(fd, buf, sizeof(buf));
  107. if (r > 0) {
  108. if (service->waiting_stopstart_timer) {
  109. service->process_timer.stop_timer(event_loop);
  110. service->waiting_stopstart_timer = false;
  111. }
  112. service->started();
  113. }
  114. else if (r == 0 || errno != EAGAIN) {
  115. if (service->waiting_stopstart_timer) {
  116. service->process_timer.stop_timer(event_loop);
  117. service->waiting_stopstart_timer = false;
  118. }
  119. service->failed_to_start(false, false);
  120. service->set_state(service_state_t::STOPPING);
  121. service->bring_down();
  122. }
  123. }
  124. else {
  125. // Just keep consuming data from the pipe:
  126. int r = bp_sys::read(fd, buf, sizeof(buf));
  127. if (r == 0) {
  128. // Process closed write end or terminated
  129. close(fd);
  130. service->notification_fd = -1;
  131. return rearm::DISARM;
  132. }
  133. }
  134. service->services->process_queues();
  135. return rearm::REARM;
  136. }
  137. dasynq::rearm service_child_watcher::status_change(eventloop_t &loop, pid_t child, int status) noexcept
  138. {
  139. base_process_service *sr = service;
  140. sr->pid = -1;
  141. sr->exit_status = bp_sys::exit_status(status);
  142. // Ok, for a process service, any process death which we didn't rig ourselves is a bit... unexpected.
  143. // Probably, the child died because we asked it to (sr->service_state == STOPPING). But even if we
  144. // didn't, there's not much we can do.
  145. // Must stop watch now since handle_exit_status might result in re-launch:
  146. // (stop_watch instead of deregister, so that we hold watch reservation).
  147. stop_watch(loop);
  148. if (sr->waiting_for_execstat) {
  149. // We still don't have an exec() status from the forked child, wait for that
  150. // before doing any further processing.
  151. return dasynq::rearm::NOOP; // hold watch reservation
  152. }
  153. if (sr->waiting_stopstart_timer) {
  154. sr->process_timer.stop_timer(loop);
  155. sr->waiting_stopstart_timer = false;
  156. }
  157. sr->handle_exit_status(bp_sys::exit_status(status));
  158. return dasynq::rearm::NOOP;
  159. }
  160. void process_service::handle_exit_status(bp_sys::exit_status exit_status) noexcept
  161. {
  162. bool did_exit = exit_status.did_exit();
  163. bool was_signalled = exit_status.was_signalled();
  164. auto service_state = get_state();
  165. if (notification_fd != -1) {
  166. readiness_watcher.deregister(event_loop);
  167. bp_sys::close(notification_fd);
  168. notification_fd = -1;
  169. }
  170. if (!exit_status.did_exit_clean() && service_state != service_state_t::STOPPING) {
  171. if (did_exit) {
  172. log(loglevel_t::ERROR, "Service ", get_name(), " process terminated with exit code ",
  173. exit_status.get_exit_status());
  174. }
  175. else if (was_signalled) {
  176. log(loglevel_t::ERROR, "Service ", get_name(), " terminated due to signal ",
  177. exit_status.get_term_sig());
  178. }
  179. }
  180. if (waiting_stopstart_timer) {
  181. process_timer.stop_timer(event_loop);
  182. waiting_stopstart_timer = false;
  183. }
  184. #if USE_UTMPX
  185. if (*inittab_id || *inittab_line) {
  186. clear_utmp_entry(inittab_id, inittab_line);
  187. }
  188. #endif
  189. if (service_state == service_state_t::STARTING) {
  190. // If state is STARTING, we must be waiting for readiness notification; the process has
  191. // terminated before becoming ready.
  192. stop_reason = stopped_reason_t::FAILED;
  193. failed_to_start();
  194. }
  195. else if (service_state == service_state_t::STOPPING) {
  196. // We won't log a non-zero exit status or termination due to signal here -
  197. // we assume that the process died because we signalled it.
  198. if (waiting_stopstart_timer) {
  199. process_timer.stop_timer(event_loop);
  200. }
  201. stopped();
  202. }
  203. else if (smooth_recovery && service_state == service_state_t::STARTED) {
  204. // unexpected termination, with smooth recovery
  205. do_smooth_recovery();
  206. return;
  207. }
  208. else {
  209. handle_unexpected_termination();
  210. }
  211. services->process_queues();
  212. }
  213. void process_service::exec_failed(run_proc_err errcode) noexcept
  214. {
  215. log(loglevel_t::ERROR, get_name(), ": execution failed - ",
  216. exec_stage_descriptions[static_cast<int>(errcode.stage)], ": ", strerror(errcode.st_errno));
  217. if (waiting_stopstart_timer) {
  218. process_timer.stop_timer(event_loop);
  219. waiting_stopstart_timer = false;
  220. }
  221. if (notification_fd != -1) {
  222. readiness_watcher.deregister(event_loop);
  223. bp_sys::close(notification_fd);
  224. notification_fd = -1;
  225. }
  226. if (get_state() == service_state_t::STARTING) {
  227. stop_reason = stopped_reason_t::EXECFAILED;
  228. failed_to_start();
  229. }
  230. else {
  231. // Process service in smooth recovery:
  232. stop_reason = stopped_reason_t::TERMINATED;
  233. unrecoverable_stop();
  234. }
  235. }
  236. void bgproc_service::handle_exit_status(bp_sys::exit_status exit_status) noexcept
  237. {
  238. // For bgproc services, receiving exit status can mean one of two things:
  239. // 1. We were launching the process, and it finished (possibly after forking). If it did fork
  240. // we want to obtain the process id of the process that we should now monitor, the actual
  241. // daemon.
  242. // 2. The above has already happened, and we are monitoring the daemon process, which has now
  243. // terminated for some reason.
  244. begin:
  245. bool did_exit = exit_status.did_exit();
  246. bool was_signalled = exit_status.was_signalled();
  247. auto service_state = get_state();
  248. if (!exit_status.did_exit_clean() && service_state != service_state_t::STOPPING) {
  249. if (did_exit) {
  250. log(loglevel_t::ERROR, "Service ", get_name(), " process terminated with exit code ",
  251. exit_status.get_exit_status());
  252. }
  253. else if (was_signalled) {
  254. log(loglevel_t::ERROR, "Service ", get_name(), " terminated due to signal ",
  255. exit_status.get_term_sig());
  256. }
  257. }
  258. if (waiting_stopstart_timer) {
  259. process_timer.stop_timer(event_loop);
  260. waiting_stopstart_timer = false;
  261. }
  262. if (doing_smooth_recovery) {
  263. doing_smooth_recovery = false;
  264. // We're either started, or stopping (i.e. we were requested to stop during smooth recovery).
  265. if (service_state == service_state_t::STOPPING) {
  266. // Stop was issued during smooth recovery
  267. if ((did_exit && exit_status.get_exit_status() != 0) || was_signalled) {
  268. stopped();
  269. }
  270. else {
  271. // We need to re-read the PID, since it has now changed.
  272. if (pid_file.length() != 0) {
  273. auto pid_result = read_pid_file(&exit_status);
  274. switch (pid_result) {
  275. case pid_result_t::FAILED:
  276. case pid_result_t::TERMINATED:
  277. // Failed startup: no auto-restart.
  278. stopped();
  279. break;
  280. case pid_result_t::OK:
  281. // We now need to bring down the daemon process
  282. bring_down();
  283. return;
  284. }
  285. }
  286. }
  287. services->process_queues();
  288. return;
  289. }
  290. else /* if (service_state == service_state_t::STARTED) */ {
  291. bool need_stop = false;
  292. if ((did_exit && exit_status.get_exit_status() != 0) || was_signalled) {
  293. need_stop = true;
  294. }
  295. else {
  296. // We need to re-read the PID, since it has now changed.
  297. if (pid_file.length() != 0) {
  298. auto pid_result = read_pid_file(&exit_status);
  299. switch (pid_result) {
  300. case pid_result_t::FAILED:
  301. // Failed startup: no auto-restart.
  302. need_stop = true;
  303. break;
  304. case pid_result_t::TERMINATED:
  305. goto begin;
  306. case pid_result_t::OK:
  307. break;
  308. }
  309. }
  310. }
  311. if (need_stop) {
  312. // Failed startup: no auto-restart.
  313. stop_reason = stopped_reason_t::TERMINATED;
  314. unrecoverable_stop();
  315. services->process_queues();
  316. }
  317. return;
  318. }
  319. }
  320. if (service_state == service_state_t::STARTING) {
  321. // POSIX requires that if the process exited clearly with a status code of 0,
  322. // the exit status value will be 0:
  323. if (exit_status.did_exit_clean()) {
  324. auto pid_result = read_pid_file(&exit_status);
  325. switch (pid_result) {
  326. case pid_result_t::FAILED:
  327. // Failed startup: no auto-restart.
  328. stop_reason = stopped_reason_t::FAILED;
  329. failed_to_start();
  330. break;
  331. case pid_result_t::TERMINATED:
  332. // started, but immediately terminated
  333. started();
  334. goto begin;
  335. case pid_result_t::OK:
  336. started();
  337. break;
  338. }
  339. }
  340. else {
  341. stop_reason = stopped_reason_t::FAILED;
  342. failed_to_start();
  343. }
  344. }
  345. else if (service_state == service_state_t::STOPPING) {
  346. // We won't log a non-zero exit status or termination due to signal here -
  347. // we assume that the process died because we signalled it.
  348. stopped();
  349. }
  350. else {
  351. // we must be STARTED
  352. if (smooth_recovery && get_target_state() == service_state_t::STARTED) {
  353. doing_smooth_recovery = true;
  354. do_smooth_recovery();
  355. if (get_state() != service_state_t::STARTED) {
  356. doing_smooth_recovery = false;
  357. }
  358. return;
  359. }
  360. handle_unexpected_termination();
  361. }
  362. services->process_queues();
  363. }
  364. void bgproc_service::exec_failed(run_proc_err errcode) noexcept
  365. {
  366. log(loglevel_t::ERROR, get_name(), ": execution failed - ",
  367. exec_stage_descriptions[static_cast<int>(errcode.stage)], ": ", strerror(errcode.st_errno));
  368. // Only time we execute is for startup:
  369. stop_reason = stopped_reason_t::EXECFAILED;
  370. failed_to_start();
  371. }
  372. void scripted_service::handle_exit_status(bp_sys::exit_status exit_status) noexcept
  373. {
  374. bool did_exit = exit_status.did_exit();
  375. bool was_signalled = exit_status.was_signalled();
  376. auto service_state = get_state();
  377. // For a scripted service, a termination occurs in one of three main cases:
  378. // - the start script completed (or failed), when service was STARTING
  379. // - the start script was interrupted to cancel startup; state is STOPPING
  380. // - the stop script complete (or failed), state is STOPPING
  381. if (service_state == service_state_t::STOPPING) {
  382. // We might be running the stop script, or we might be running the start script and have issued
  383. // a cancel order via SIGINT:
  384. if (interrupting_start) {
  385. if (waiting_stopstart_timer) {
  386. process_timer.stop_timer(event_loop);
  387. waiting_stopstart_timer = false;
  388. }
  389. // We issued a start interrupt, so we expected this failure:
  390. if (did_exit && exit_status.get_exit_status() != 0) {
  391. log(loglevel_t::NOTICE, "Service ", get_name(), " start cancelled; exit code ",
  392. exit_status.get_exit_status());
  393. // Assume that a command terminating normally (with failure status) requires no cleanup:
  394. stopped();
  395. }
  396. else {
  397. if (was_signalled) {
  398. log(loglevel_t::NOTICE, "Service ", get_name(), " start cancelled from signal ",
  399. exit_status.get_term_sig());
  400. }
  401. // If the start script completed successfully, or was interrupted via our signal,
  402. // we want to run the stop script to clean up:
  403. bring_down();
  404. }
  405. interrupting_start = false;
  406. }
  407. else if (exit_status.did_exit_clean()) {
  408. // We were running the stop script and finished successfully
  409. stopped();
  410. }
  411. else {
  412. // ??? failed to stop! Let's log it as warning:
  413. if (did_exit) {
  414. log(loglevel_t::WARN, "Service ", get_name(), " stop command failed with exit code ",
  415. exit_status.get_exit_status());
  416. }
  417. else if (was_signalled) {
  418. log(loglevel_t::WARN, "Service ", get_name(), " stop command terminated due to signal ",
  419. exit_status.get_term_sig());
  420. }
  421. // Even if the stop script failed, assume that service is now stopped, so that any dependencies
  422. // can be stopped. There's not really any other useful course of action here.
  423. stopped();
  424. }
  425. services->process_queues();
  426. }
  427. else { // STARTING
  428. if (exit_status.did_exit_clean()) {
  429. started();
  430. }
  431. else if (was_signalled && exit_status.get_term_sig() == SIGINT && onstart_flags.skippable) {
  432. // A skippable service can be skipped by interrupting (eg by ^C if the service
  433. // starts on the console).
  434. start_skipped = true;
  435. started();
  436. }
  437. else {
  438. // failed to start
  439. if (did_exit) {
  440. log(loglevel_t::ERROR, "Service ", get_name(), " command failed with exit code ",
  441. exit_status.get_exit_status());
  442. }
  443. else if (was_signalled) {
  444. log(loglevel_t::ERROR, "Service ", get_name(), " command terminated due to signal ",
  445. exit_status.get_term_sig());
  446. }
  447. stop_reason = stopped_reason_t::FAILED;
  448. failed_to_start();
  449. }
  450. services->process_queues();
  451. }
  452. }
  453. void scripted_service::exec_failed(run_proc_err errcode) noexcept
  454. {
  455. log(loglevel_t::ERROR, get_name(), ": execution failed - ",
  456. exec_stage_descriptions[static_cast<int>(errcode.stage)], ": ", strerror(errcode.st_errno));
  457. auto service_state = get_state();
  458. if (service_state == service_state_t::STARTING) {
  459. stop_reason = stopped_reason_t::EXECFAILED;
  460. failed_to_start();
  461. }
  462. else if (service_state == service_state_t::STOPPING) {
  463. // We've logged the failure, but it's probably better not to leave the service in
  464. // STOPPING state:
  465. stopped();
  466. }
  467. }
  468. // Return a value as an unsigned-type value.
  469. template <typename T> typename std::make_unsigned<T>::type make_unsigned_val(T val)
  470. {
  471. return static_cast<typename std::make_unsigned<T>::type>(val);
  472. }
  473. bgproc_service::pid_result_t
  474. bgproc_service::read_pid_file(bp_sys::exit_status *exit_status) noexcept
  475. {
  476. const char *pid_file_c = pid_file.c_str();
  477. int fd = bp_sys::open(pid_file_c, O_CLOEXEC);
  478. if (fd == -1) {
  479. log(loglevel_t::ERROR, get_name(), ": read pid file: ", strerror(errno));
  480. return pid_result_t::FAILED;
  481. }
  482. char pidbuf[21]; // just enough to hold any 64-bit integer
  483. int r = complete_read(fd, pidbuf, 20);
  484. if (r < 0) {
  485. // Could not read from PID file
  486. log(loglevel_t::ERROR, get_name(), ": could not read from pidfile; ", strerror(errno));
  487. bp_sys::close(fd);
  488. return pid_result_t::FAILED;
  489. }
  490. bp_sys::close(fd);
  491. pidbuf[r] = 0; // store nul terminator
  492. bool valid_pid = false;
  493. try {
  494. unsigned long long v = std::stoull(pidbuf, nullptr, 0);
  495. if (v <= make_unsigned_val(std::numeric_limits<pid_t>::max())) {
  496. pid = (pid_t) v;
  497. valid_pid = true;
  498. }
  499. }
  500. catch (std::out_of_range &exc) {
  501. // Too large?
  502. }
  503. catch (std::invalid_argument &exc) {
  504. // Ok, so it doesn't look like a number: proceed...
  505. }
  506. if (valid_pid) {
  507. pid_t wait_r = waitpid(pid, exit_status, WNOHANG);
  508. if (wait_r == -1 && errno == ECHILD) {
  509. // We can't track this child - check process exists:
  510. if (bp_sys::kill(pid, 0) == 0 || errno != ESRCH) {
  511. tracking_child = false;
  512. return pid_result_t::OK;
  513. }
  514. else {
  515. log(loglevel_t::ERROR, get_name(), ": pid read from pidfile (", pid, ") is not valid");
  516. pid = -1;
  517. return pid_result_t::FAILED;
  518. }
  519. }
  520. else if (wait_r == pid) {
  521. pid = -1;
  522. return pid_result_t::TERMINATED;
  523. }
  524. else if (wait_r == 0) {
  525. // We can track the child
  526. child_listener.add_reserved(event_loop, pid, dasynq::DEFAULT_PRIORITY - 10);
  527. tracking_child = true;
  528. reserved_child_watch = true;
  529. return pid_result_t::OK;
  530. }
  531. }
  532. log(loglevel_t::ERROR, get_name(), ": pid read from pidfile (", pid, ") is not valid");
  533. pid = -1;
  534. return pid_result_t::FAILED;
  535. }
  536. void process_service::bring_down() noexcept
  537. {
  538. if (waiting_for_execstat) {
  539. // The process is still starting. This should be uncommon, but can occur during
  540. // smooth recovery. We can't do much now; we have to wait until we get the
  541. // status, and then act appropriately.
  542. return;
  543. }
  544. else if (pid != -1) {
  545. // The process is still kicking on - must actually kill it. We signal the process
  546. // group (-pid) rather than just the process as there's less risk then of creating
  547. // an orphaned process group:
  548. if (term_signal != 0) {
  549. kill_pg(term_signal);
  550. }
  551. // If there's a stop timeout, arm the timer now:
  552. if (stop_timeout != time_val(0,0)) {
  553. process_timer.arm_timer_rel(event_loop, stop_timeout);
  554. waiting_stopstart_timer = true;
  555. }
  556. // The rest is done in handle_exit_status.
  557. }
  558. else {
  559. // The process is already dead.
  560. if (waiting_restart_timer) {
  561. process_timer.stop_timer(event_loop);
  562. waiting_restart_timer = false;
  563. }
  564. stopped();
  565. }
  566. }
  567. void bgproc_service::bring_down() noexcept
  568. {
  569. if (pid != -1) {
  570. // The process is still kicking on - must actually kill it. We signal the process
  571. // group (-pid) rather than just the process as there's less risk then of creating
  572. // an orphaned process group:
  573. if (term_signal != 0) {
  574. kill_pg(SIGTERM);
  575. }
  576. // In most cases, the rest is done in handle_exit_status.
  577. // If we are a BGPROCESS and the process is not our immediate child, however, that
  578. // won't work - check for this now:
  579. if (! tracking_child) {
  580. stopped();
  581. }
  582. else if (stop_timeout != time_val(0,0)) {
  583. process_timer.arm_timer_rel(event_loop, stop_timeout);
  584. waiting_stopstart_timer = true;
  585. }
  586. }
  587. else {
  588. // The process is already dead.
  589. stopped();
  590. }
  591. }
  592. void scripted_service::bring_down() noexcept
  593. {
  594. if (pid != -1) {
  595. // We're already running the stop script; nothing to do.
  596. return;
  597. }
  598. if (stop_command.length() == 0) {
  599. stopped();
  600. }
  601. else if (! start_ps_process(stop_arg_parts, false)) {
  602. // Couldn't execute stop script, but there's not much we can do:
  603. stopped();
  604. }
  605. else {
  606. // successfully started stop script: start kill timer:
  607. if (stop_timeout != time_val(0,0)) {
  608. process_timer.arm_timer_rel(event_loop, stop_timeout);
  609. waiting_stopstart_timer = true;
  610. }
  611. }
  612. }
  613. dasynq::rearm process_restart_timer::timer_expiry(eventloop_t &, int expiry_count)
  614. {
  615. service->timer_expired();
  616. // Leave the timer disabled, or, if it has been reset by any processing above, leave it armed:
  617. return dasynq::rearm::NOOP;
  618. }