dinit.cc 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  1. #include <iostream>
  2. #include <fstream>
  3. #include <list>
  4. #include <cstring>
  5. #include <csignal>
  6. #include <cstddef>
  7. #include <cstdlib>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <sys/un.h>
  11. #include <sys/socket.h>
  12. #include <unistd.h>
  13. #include <fcntl.h>
  14. #include <pwd.h>
  15. #include <termios.h>
  16. #ifdef __linux__
  17. #include <sys/prctl.h>
  18. #include <sys/klog.h>
  19. #include <sys/reboot.h>
  20. #endif
  21. #if defined(__FreeBSD__) || defined(__DragonFly__)
  22. #include <sys/procctl.h>
  23. #endif
  24. #include <dasynq.h>
  25. #include "dinit.h"
  26. #include "service.h"
  27. #include "control.h"
  28. #include "dinit-log.h"
  29. #include "dinit-socket.h"
  30. #include "static-string.h"
  31. #include "dinit-utmp.h"
  32. #include "dinit-env.h"
  33. #include "options-processing.h"
  34. #include "mconfig.h"
  35. /*
  36. * When running as the system init process, Dinit processes the following signals:
  37. *
  38. * SIGTERM - roll back services and then fork/exec /sbin/halt
  39. * SIGINT - roll back services and then fork/exec /sbin/reboot
  40. * SIGQUIT - exec() /sbin/shutdown without rolling back services
  41. *
  42. * It's an open question about whether Dinit should roll back services *before*
  43. * running halt/reboot, since those commands should prompt rollback of services
  44. * anyway. But it seems safe to do so, and it means the user can at least stop
  45. * services even if the halt/reboot commands are unavailable for some reason.
  46. */
  47. using namespace cts;
  48. using eventloop_t = dasynq::event_loop<dasynq::null_mutex>;
  49. eventloop_t event_loop(dasynq::delayed_init {});
  50. static void sigint_reboot_cb(eventloop_t &eloop) noexcept;
  51. static void sigquit_cb(eventloop_t &eloop) noexcept;
  52. static void sigterm_cb(eventloop_t &eloop) noexcept;
  53. static bool open_control_socket(bool report_ro_failure = true) noexcept;
  54. static void close_control_socket() noexcept;
  55. static void control_socket_ready() noexcept;
  56. static void confirm_restart_boot() noexcept;
  57. static void flush_log() noexcept;
  58. static void control_socket_cb(eventloop_t *loop, int fd) noexcept;
  59. #ifdef SUPPORT_CGROUPS
  60. static void find_cgroup_path() noexcept;
  61. #endif
  62. static void printVersion();
  63. // Variables
  64. static dirload_service_set *services;
  65. static bool am_system_mgr = false; // true if we are PID 1
  66. static bool am_system_init = false; // true if we are the system init process
  67. static bool did_log_boot = false;
  68. static bool control_socket_open = false;
  69. bool external_log_open = false;
  70. int active_control_conns = 0;
  71. int socket_ready_fd = -1;
  72. // Control socket path. We maintain a string (control_socket_str) in case we need
  73. // to allocate storage, but control_socket_path is the authoritative value.
  74. static const char *control_socket_path = SYSCONTROLSOCKET;
  75. static std::string control_socket_str;
  76. static const char *env_file_path = "/etc/dinit/environment";
  77. static const char *log_path = "/dev/log";
  78. static bool log_is_syslog = true; // if false, log is a file
  79. // Set to true (when console_input_watcher is active) if console input becomes available
  80. static bool console_input_ready = false;
  81. #ifdef SUPPORT_CGROUPS
  82. // Path of the root cgroup according to dinit. This will be dinit's own cgroup path.
  83. std::string cgroups_path;
  84. bool have_cgroups_path = false;
  85. #endif
  86. namespace {
  87. // Event-loop handler for a signal, which just delegates to a function (pointer).
  88. class callback_signal_handler : public eventloop_t::signal_watcher_impl<callback_signal_handler>
  89. {
  90. using rearm = dasynq::rearm;
  91. public:
  92. typedef void (*cb_func_t)(eventloop_t &);
  93. private:
  94. cb_func_t cb_func;
  95. public:
  96. callback_signal_handler() : cb_func(nullptr) { }
  97. callback_signal_handler(cb_func_t pcb_func) : cb_func(pcb_func) { }
  98. void set_cb_func(cb_func_t cb_func)
  99. {
  100. this->cb_func = cb_func;
  101. }
  102. rearm received(eventloop_t &eloop, int signo, siginfo_p siginfo)
  103. {
  104. cb_func(eloop);
  105. return rearm::REARM;
  106. }
  107. };
  108. // Event-loop handler for when a connection is made to the control socket.
  109. class control_socket_watcher : public eventloop_t::fd_watcher_impl<control_socket_watcher>
  110. {
  111. using rearm = dasynq::rearm;
  112. public:
  113. rearm fd_event(eventloop_t &loop, int fd, int flags) noexcept
  114. {
  115. control_socket_cb(&loop, fd);
  116. return rearm::REARM;
  117. }
  118. };
  119. // Watch for console input and set a flag when it is available.
  120. class console_input_watcher : public eventloop_t::fd_watcher_impl<console_input_watcher>
  121. {
  122. using rearm = dasynq::rearm;
  123. public:
  124. rearm fd_event(eventloop_t &loop, int fd, int flags) noexcept
  125. {
  126. console_input_ready = true;
  127. return rearm::DISARM;
  128. }
  129. };
  130. // Simple timer used to limit the amount of time waiting for the log flush to complete (at shutdown)
  131. class log_flush_timer_t : public eventloop_t::timer_impl<log_flush_timer_t>
  132. {
  133. using rearm = dasynq::rearm;
  134. bool expired;
  135. public:
  136. rearm timer_expiry(eventloop_t &, int expiry_count)
  137. {
  138. expired = true;
  139. return rearm::DISARM;
  140. }
  141. bool has_expired()
  142. {
  143. return expired;
  144. }
  145. void reset()
  146. {
  147. expired = false;
  148. }
  149. };
  150. control_socket_watcher control_socket_io;
  151. console_input_watcher console_input_io;
  152. log_flush_timer_t log_flush_timer;
  153. // These need to be at namespace scope to prevent causing stack allocations when using them:
  154. constexpr auto shutdown_exec = literal(SBINDIR) + "/" + SHUTDOWN_PREFIX + "shutdown";
  155. constexpr auto error_exec_sd = literal("Error executing ") + shutdown_exec + ": ";
  156. }
  157. // Options handled in dinit_main
  158. struct options {
  159. const char * env_file = nullptr;
  160. bool control_socket_path_set = false;
  161. bool env_file_set = false;
  162. bool log_specified = false;
  163. bool process_sys_args = false;
  164. service_dir_opt service_dir_opts;
  165. // list of services to start
  166. std::list<const char *> services_to_start;
  167. };
  168. // Process a command line argument (and possibly its follow-up value)
  169. // Returns -1 for clean exit required, 0 for success, 1 for error exit required
  170. static int process_commandline_arg(char **argv, int argc, int &i, options &opts)
  171. {
  172. using std::cerr;
  173. using std::cout;
  174. using std::endl;
  175. using std::list;
  176. const char * &env_file = opts.env_file;
  177. bool &control_socket_path_set = opts.control_socket_path_set;
  178. bool &env_file_set = opts.env_file_set;
  179. bool &log_specified = opts.log_specified;
  180. service_dir_opt &service_dir_opts = opts.service_dir_opts;
  181. list<const char *> &services_to_start = opts.services_to_start;
  182. if (argv[i][0] == '-') {
  183. // An option...
  184. if (strcmp(argv[i], "--env-file") == 0 || strcmp(argv[i], "-e") == 0) {
  185. if (++i < argc) {
  186. env_file_set = true;
  187. env_file = argv[i];
  188. }
  189. else {
  190. cerr << "dinit: '--env-file' (-e) requires an argument\n";
  191. return 1;
  192. }
  193. }
  194. else if (strcmp(argv[i], "--services-dir") == 0 || strcmp(argv[i], "-d") == 0) {
  195. if (++i < argc) {
  196. service_dir_opts.set_specified_service_dir(argv[i]);
  197. }
  198. else {
  199. cerr << "dinit: '--services-dir' (-d) requires an argument\n";
  200. return 1;
  201. }
  202. }
  203. else if (strcmp(argv[i], "--system") == 0 || strcmp(argv[i], "-s") == 0) {
  204. am_system_init = true;
  205. }
  206. else if (strcmp(argv[i], "--system-mgr") == 0 || strcmp(argv[i], "-m") == 0) {
  207. am_system_mgr = true;
  208. opts.process_sys_args = false;
  209. }
  210. else if (strcmp(argv[i], "--user") == 0 || strcmp(argv[i], "-u") == 0) {
  211. am_system_init = false;
  212. }
  213. else if (strcmp(argv[i], "--container") == 0 || strcmp(argv[i], "-o") == 0) {
  214. am_system_mgr = false;
  215. opts.process_sys_args = false;
  216. }
  217. else if (strcmp(argv[i], "--socket-path") == 0 || strcmp(argv[i], "-p") == 0) {
  218. if (++i < argc) {
  219. control_socket_path = argv[i];
  220. control_socket_path_set = true;
  221. }
  222. else {
  223. cerr << "dinit: '--socket-path' (-p) requires an argument\n";
  224. return 1;
  225. }
  226. }
  227. else if (strcmp(argv[i], "--ready-fd") == 0 || strcmp(argv[i], "-F") == 0) {
  228. if (++i < argc) {
  229. char *endp = nullptr;
  230. auto fdn = strtoul(argv[i], &endp, 10);
  231. if (endp == argv[i] || *endp) {
  232. cerr << "dinit: '--ready-fd' (-F) requires a numerical argument\n";
  233. return 1;
  234. }
  235. socket_ready_fd = int(fdn);
  236. auto fl = fcntl(socket_ready_fd, F_GETFD);
  237. // We also want to make sure stdin is not allowed
  238. if (socket_ready_fd == 0 || fl < 0) {
  239. cerr << "dinit: '--ready-fd' (-F) requires an open file descriptor\n";
  240. return 1;
  241. }
  242. // Leave standard file descriptors alone, but make sure
  243. // anything else is not leaked to child processes
  244. if (socket_ready_fd > 2) {
  245. fcntl(socket_ready_fd, F_SETFD, FD_CLOEXEC | fl);
  246. }
  247. }
  248. else {
  249. cerr << "dinit: '--ready-fd' (-F) requires an argument\n";
  250. return 1;
  251. }
  252. }
  253. else if (strcmp(argv[i], "--log-file") == 0 || strcmp(argv[i], "-l") == 0) {
  254. if (++i < argc) {
  255. log_path = argv[i];
  256. log_is_syslog = false;
  257. log_specified = true;
  258. }
  259. else {
  260. cerr << "dinit: '--log-file' (-l) requires an argument\n";
  261. return 1;
  262. }
  263. }
  264. else if (strcmp(argv[i], "--quiet") == 0 || strcmp(argv[i], "-q") == 0) {
  265. console_service_status = false;
  266. log_level[DLOG_CONS] = loglevel_t::ZERO;
  267. }
  268. #ifdef SUPPORT_CGROUPS
  269. else if (strcmp(argv[i], "--cgroup-path") == 0 || strcmp(argv[i], "-b") == 0) {
  270. if (++i < argc) {
  271. cgroups_path = argv[i];
  272. have_cgroups_path = true;
  273. }
  274. else {
  275. cerr << "dinit: '--cgroup-path' (-b) requires an argument\n";
  276. return 1;
  277. }
  278. }
  279. #endif
  280. else if (strcmp(argv[i], "--service") == 0 || strcmp(argv[i], "-t") == 0) {
  281. if (++i < argc) {
  282. services_to_start.push_back(argv[i]);
  283. }
  284. else {
  285. cerr << "dinit: '--service' (-t) requires an argument\n";
  286. return 1;
  287. }
  288. }
  289. else if (strcmp(argv[i], "--version") == 0) {
  290. printVersion();
  291. return -1;
  292. }
  293. else if (strcmp(argv[i], "--help") == 0) {
  294. cout << "dinit: init/service manager daemon\n"
  295. " --help display (this) help\n"
  296. " --version display version\n"
  297. " --env-file <file>, -e <file>\n"
  298. " environment variable initialisation file\n"
  299. " --services-dir <dir>, -d <dir>\n"
  300. " set base directory for service description\n"
  301. " files, can be specified multiple times\n"
  302. " --system, -s run as the system service manager\n"
  303. " --system-mgr, -m run as system manager (perform shutdown etc)\n"
  304. " --user, -u run as a user service manager\n"
  305. " --container, -o run in container mode (do not manage system)\n"
  306. " --socket-path <path>, -p <path>\n"
  307. " path to control socket\n"
  308. " --ready-fd <fd>, -F <fd>\n"
  309. " file descriptor to report readiness\n"
  310. #ifdef SUPPORT_CGROUPS
  311. " --cgroup-path <path>, -b <path>\n"
  312. " cgroup base path (for resolving relative paths)\n"
  313. #endif
  314. " --log-file <file>, -l <file> log to the specified file\n"
  315. " --quiet, -q disable output to standard output\n"
  316. " <service-name>, --service <service-name>, -t <service-name>\n"
  317. " start service with name <service-name>\n";
  318. return -1;
  319. }
  320. else {
  321. // unrecognized
  322. if (!opts.process_sys_args) {
  323. cerr << "dinit: unrecognized option: " << argv[i] << endl;
  324. return 1;
  325. }
  326. }
  327. }
  328. else {
  329. #ifdef __linux__
  330. // If we are running as init (PID=1), the Linux kernel gives us all command line arguments it was
  331. // given but didn't recognize, and, uh, *some* that it did recognize, which means we can't assume
  332. // that anything is a service name (for example "nopti" seems to get passed through to init).
  333. // However, we can look for special names that we know aren't kernel parameters, such as "single".
  334. //
  335. // (Note this may have been fixed in recent kernels: see changelog for 5.15.46/5.18.3,
  336. // "x86: Fix return value of __setup handlers")
  337. //
  338. // LILO puts "auto" on the command line for unattended boots, but we don't care about that and want
  339. // it filtered.
  340. //
  341. // We don't expect to see options beginning with '-' appear on the kernel command line either, so we
  342. // can interpret those as dinit arguments. In particular if we see -m or -o, we assume that every
  343. // name we see from then is a service name (i.e. process_sys_args is set false when we seem them,
  344. // see above).
  345. //
  346. // (Note, you can give "--" on the kernel command line to pass every option from that point to init
  347. // directly, but init doesn't see the "--" itself, which makes it less useful, since we still can't
  348. // tell whether a "name" was intended as a kernel parameter or init parameter).
  349. // So, long story short: if we think we're PID 1 and we haven't seen -m or -c options yet, only
  350. // recognise "single" as a service name and ignore everything else.
  351. if (!opts.process_sys_args || strcmp(argv[i], "single") == 0) {
  352. services_to_start.push_back(argv[i]);
  353. }
  354. #else
  355. services_to_start.push_back(argv[i]);
  356. #endif
  357. }
  358. return 0;
  359. }
  360. // Main entry point
  361. int dinit_main(int argc, char **argv)
  362. {
  363. using namespace std;
  364. am_system_mgr = (getpid() == 1);
  365. am_system_init = (getuid() == 0);
  366. struct options opts;
  367. // if we are PID 1 and user id 0, we are *most probably* the system init. (Or on linux at least, we
  368. // could instead be in a container; then we expect -o argument and unset this then).
  369. opts.process_sys_args = am_system_mgr && am_system_init;
  370. const char * &env_file = opts.env_file;
  371. bool &control_socket_path_set = opts.control_socket_path_set;
  372. bool &env_file_set = opts.env_file_set;
  373. bool &log_specified = opts.log_specified;
  374. service_dir_opt &service_dir_opts = opts.service_dir_opts;
  375. list<const char *> &services_to_start = opts.services_to_start;
  376. for (int i = 1; i < argc; i++) {
  377. int p = process_commandline_arg(argv, argc, i, opts);
  378. if (p == -1) {
  379. // clean exit
  380. return 0;
  381. }
  382. if (p == 1) {
  383. // error exit
  384. return 1;
  385. }
  386. }
  387. if (am_system_mgr) {
  388. // setup STDIN, STDOUT, STDERR so that we can use them
  389. int onefd = open("/dev/console", O_RDONLY, 0);
  390. if (onefd != -1) {
  391. dup2(onefd, 0);
  392. }
  393. int twofd = open("/dev/console", O_RDWR, 0);
  394. if (twofd != -1) {
  395. dup2(twofd, 1);
  396. dup2(twofd, 2);
  397. }
  398. if (onefd > 2) close(onefd);
  399. if (twofd > 2) close(twofd);
  400. if (! env_file_set) {
  401. env_file = env_file_path;
  402. }
  403. // we will assume an empty cgroups root path
  404. #if SUPPORT_CGROUPS
  405. have_cgroups_path = true;
  406. #endif
  407. }
  408. /* Set up signal handlers etc */
  409. sigset_t sigwait_set;
  410. sigemptyset(&sigwait_set);
  411. sigaddset(&sigwait_set, SIGCHLD);
  412. sigaddset(&sigwait_set, SIGINT);
  413. sigaddset(&sigwait_set, SIGTERM);
  414. if (am_system_mgr) sigaddset(&sigwait_set, SIGQUIT);
  415. sigprocmask(SIG_BLOCK, &sigwait_set, NULL);
  416. // Terminal access control signals - we ignore these so that dinit can't be
  417. // suspended if it writes to the terminal after some other process has claimed
  418. // ownership of it.
  419. signal(SIGTSTP, SIG_IGN);
  420. signal(SIGTTIN, SIG_IGN);
  421. signal(SIGTTOU, SIG_IGN);
  422. signal(SIGPIPE, SIG_IGN);
  423. event_loop.init();
  424. if (!am_system_init && !control_socket_path_set) {
  425. const char * rundir = getenv("XDG_RUNTIME_DIR");
  426. const char * sockname = "dinitctl";
  427. if (rundir == nullptr) {
  428. rundir = service_dir_opt::get_user_home();
  429. sockname = ".dinitctl";
  430. }
  431. if (rundir != nullptr) {
  432. control_socket_str = rundir;
  433. control_socket_str.push_back('/');
  434. control_socket_str += sockname;
  435. control_socket_path = control_socket_str.c_str();
  436. }
  437. }
  438. if (services_to_start.empty()) {
  439. services_to_start.push_back("boot");
  440. }
  441. // Set up signal handlers
  442. callback_signal_handler sigterm_watcher {sigterm_cb};
  443. callback_signal_handler sigint_watcher;
  444. callback_signal_handler sigquit_watcher;
  445. if (am_system_mgr) {
  446. sigint_watcher.set_cb_func(sigint_reboot_cb);
  447. sigquit_watcher.set_cb_func(sigquit_cb);
  448. }
  449. else {
  450. sigint_watcher.set_cb_func(sigterm_cb);
  451. }
  452. sigint_watcher.add_watch(event_loop, SIGINT);
  453. sigterm_watcher.add_watch(event_loop, SIGTERM);
  454. if (am_system_mgr) {
  455. // PID 1: we may ask for console input; SIGQUIT exec's shutdown
  456. console_input_io.add_watch(event_loop, STDIN_FILENO, dasynq::IN_EVENTS, false);
  457. sigquit_watcher.add_watch(event_loop, SIGQUIT);
  458. // (If not PID 1, we instead just let SIGQUIT perform the default action.)
  459. }
  460. init_log(log_is_syslog);
  461. log_flush_timer.add_timer(event_loop, dasynq::clock_type::MONOTONIC);
  462. #if SUPPORT_CGROUPS
  463. if (!have_cgroups_path) {
  464. find_cgroup_path();
  465. // We will press on if the cgroup root path could not be identified, since services might
  466. // not require cgroups anyway and/or might only specify absolute cgroups paths.
  467. }
  468. #endif
  469. // Try to open control socket (may fail due to readonly filesystem, we ignore that if we are
  470. // system init)
  471. if (!open_control_socket(!am_system_init)) {
  472. flush_log();
  473. return EXIT_FAILURE;
  474. }
  475. #ifdef __linux__
  476. if (am_system_mgr) {
  477. // Disable non-critical kernel output to console
  478. klogctl(6 /* SYSLOG_ACTION_CONSOLE_OFF */, nullptr, 0);
  479. // Make ctrl+alt+del combination send SIGINT to PID 1 (this process)
  480. reboot(RB_DISABLE_CAD);
  481. }
  482. // Mark ourselves as a subreaper. This means that if a process we start double-forks, the
  483. // orphaned child will re-parent to us rather than to PID 1 (although that could be us too).
  484. prctl(PR_SET_CHILD_SUBREAPER, 1);
  485. #elif defined(__FreeBSD__) || defined(__DragonFly__)
  486. // Documentation (man page) for this kind-of sucks. PROC_REAP_ACQUIRE "acquires the reaper status for
  487. // the current process" but does that mean the first two arguments still need valid values to be
  488. // supplied? We'll play it safe and explicitly target our own process:
  489. procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL);
  490. #endif
  491. service_dir_opts.build_paths(am_system_init);
  492. // Start requested services
  493. services = new dirload_service_set(std::move(service_dir_opts.get_paths()));
  494. setup_log_console_handoff(services);
  495. if (am_system_init) {
  496. log(loglevel_t::NOTICE, false, "Starting system");
  497. }
  498. // Only try to set up the external log now if we aren't the system init. (If we are the
  499. // system init, wait until the log service starts).
  500. if (!am_system_init || log_specified) setup_external_log();
  501. if (env_file != nullptr) {
  502. read_env_file(env_file, true, main_env);
  503. }
  504. for (auto svc : services_to_start) {
  505. try {
  506. services->start_service(svc);
  507. // Note in general if we fail to start a service we don't need any special error handling,
  508. // since we either leave other services running or, if it was the only service, then no
  509. // services will be running and we will process normally (reboot if system process,
  510. // exit if user process).
  511. }
  512. catch (service_not_found &snf) {
  513. log(loglevel_t::ERROR, snf.service_name, ": could not find service description.");
  514. }
  515. catch (service_description_exc &sde) {
  516. log_service_load_failure(sde);
  517. }
  518. catch (service_load_exc &sle) {
  519. log(loglevel_t::ERROR, sle.service_name, ": ", sle.exc_description);
  520. }
  521. catch (std::bad_alloc &badalloce) {
  522. log(loglevel_t::ERROR, "Out of memory when trying to start service: ", svc, ".");
  523. break;
  524. }
  525. }
  526. // Notify readiness just before the event loop starts (and after services
  527. // are scheduled to start). If the socket is not ready yet (may be in case
  528. // of read-only file system), we will report it when it is.
  529. control_socket_ready();
  530. run_event_loop:
  531. // Process events until all services have terminated.
  532. while (services->count_active_services() != 0) {
  533. event_loop.run();
  534. }
  535. shutdown_type_t shutdown_type = services->get_shutdown_type();
  536. if (shutdown_type == shutdown_type_t::REMAIN) {
  537. goto run_event_loop;
  538. }
  539. if (am_system_mgr) {
  540. log_msg_begin(loglevel_t::NOTICE, "No more active services.");
  541. if (shutdown_type == shutdown_type_t::REBOOT) {
  542. log_msg_end(" Will reboot.");
  543. }
  544. else if (shutdown_type == shutdown_type_t::HALT) {
  545. log_msg_end(" Will halt.");
  546. }
  547. else if (shutdown_type == shutdown_type_t::POWEROFF) {
  548. log_msg_end(" Will power down.");
  549. }
  550. }
  551. flush_log();
  552. close_control_socket();
  553. if (am_system_mgr) {
  554. if (shutdown_type == shutdown_type_t::NONE) {
  555. // Services all stopped but there was no shutdown issued. Inform user, wait for ack, and
  556. // re-start boot sequence.
  557. sync(); // Sync to minimise data loss if user elects to power off / hard reset
  558. confirm_restart_boot();
  559. if (services->count_active_services() != 0) {
  560. // Recovery service started
  561. goto run_event_loop;
  562. }
  563. shutdown_type = services->get_shutdown_type();
  564. if (shutdown_type == shutdown_type_t::NONE) {
  565. try {
  566. services->start_service("boot");
  567. goto run_event_loop; // yes, the "evil" goto
  568. }
  569. catch (...) {
  570. // Couldn't start boot service, let's reboot the system
  571. log(loglevel_t::ERROR, "Could not start 'boot' service. Will attempt reboot.");
  572. shutdown_type = shutdown_type_t::REBOOT;
  573. }
  574. }
  575. }
  576. const char * cmd_arg;
  577. if (shutdown_type == shutdown_type_t::HALT) {
  578. cmd_arg = "-h";
  579. }
  580. else if (shutdown_type == shutdown_type_t::REBOOT) {
  581. cmd_arg = "-r";
  582. }
  583. else {
  584. // power off.
  585. cmd_arg = "-p";
  586. }
  587. // Fork and execute dinit-reboot.
  588. execl(shutdown_exec.c_str(), shutdown_exec.c_str(), "--system", cmd_arg, nullptr);
  589. log(loglevel_t::ERROR, error_exec_sd, strerror(errno));
  590. // PID 1 must not actually exit, although we should never reach this point:
  591. while (true) {
  592. event_loop.run();
  593. }
  594. }
  595. else if (shutdown_type == shutdown_type_t::REBOOT) {
  596. // Non-system-process. If we got SIGINT, let's die due to it:
  597. sigset_t sigwait_set_int;
  598. sigemptyset(&sigwait_set_int);
  599. sigaddset(&sigwait_set_int, SIGINT);
  600. raise(SIGINT);
  601. sigprocmask(SIG_UNBLOCK, &sigwait_set_int, NULL);
  602. }
  603. return 0;
  604. }
  605. // Get user confirmation before proceeding with restarting boot sequence.
  606. // Returns after confirmation, possibly with shutdown type altered.
  607. static void confirm_restart_boot() noexcept
  608. {
  609. // Bypass log; we want to make certain the message is seen:
  610. std::cout << "All services have stopped with no shutdown issued; boot failure?\n";
  611. // Drain input, set non-canonical input mode (receive characters as they are typed)
  612. struct termios term_attr;
  613. if (tcgetattr(STDIN_FILENO, &term_attr) != 0) {
  614. // Not a terminal?
  615. std::cout << "Halting." << std::endl;
  616. services->stop_all_services(shutdown_type_t::HALT);
  617. return;
  618. }
  619. term_attr.c_lflag &= ~ICANON;
  620. tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_attr);
  621. // Set non-blocking mode
  622. int origFlags = fcntl(STDIN_FILENO, F_GETFL);
  623. fcntl(STDIN_FILENO, F_SETFL, origFlags | O_NONBLOCK);
  624. do_prompt:
  625. std::cout << "Choose: (r)eboot, r(e)covery, re(s)tart boot sequence, (p)ower off? " << std::flush;
  626. console_input_io.set_enabled(event_loop, true);
  627. do {
  628. event_loop.run();
  629. } while (! console_input_ready && services->get_shutdown_type() == shutdown_type_t::NONE);
  630. console_input_io.set_enabled(event_loop, false);
  631. // We either have input, or shutdown type has been set, or both.
  632. if (console_input_ready) {
  633. console_input_ready = false;
  634. char buf[1];
  635. int r = read(STDIN_FILENO, buf, 1); // read a single character, to make sure we wait for input
  636. if (r == 1) {
  637. std::cout << "\n"; // force new line after input
  638. if (buf[0] == 'r' || buf[0] == 'R') {
  639. services->stop_all_services(shutdown_type_t::REBOOT);
  640. }
  641. else if (buf[0] == 'e' || buf[0] == 'E') {
  642. try {
  643. services->start_service("recovery");
  644. }
  645. catch (...) {
  646. std::cout << "Unable to start recovery service.\n";
  647. goto do_prompt;
  648. }
  649. }
  650. else if (buf[0] == 's' || buf[0] == 'S') {
  651. // nothing - leave no shutdown type
  652. }
  653. else if (buf[0] == 'p' || buf[0] == 'P') {
  654. services->stop_all_services(shutdown_type_t::POWEROFF);
  655. }
  656. else {
  657. goto do_prompt;
  658. }
  659. }
  660. tcflush(STDIN_FILENO, TCIFLUSH); // discard the rest of input
  661. }
  662. term_attr.c_lflag |= ICANON;
  663. tcsetattr(STDIN_FILENO, TCSANOW, &term_attr);
  664. fcntl(STDIN_FILENO, F_SETFL, origFlags);
  665. }
  666. // Callback for control socket
  667. static void control_socket_cb(eventloop_t *loop, int sockfd) noexcept
  668. {
  669. // Considered keeping a limit the number of active connections, however, there doesn't
  670. // seem much to be gained from that. Only root can create connections and not being
  671. // able to establish a control connection is as much a denial-of-service as is not being
  672. // able to start a service due to lack of fd's.
  673. // Accept a connection
  674. int newfd = dinit_accept4(sockfd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
  675. if (newfd != -1) {
  676. try {
  677. new control_conn_t(*loop, services, newfd); // will delete itself when it's finished
  678. }
  679. catch (std::exception &exc) {
  680. log(loglevel_t::ERROR, "Error accepting control connection: ", exc.what());
  681. close(newfd);
  682. }
  683. }
  684. }
  685. static void control_socket_ready() noexcept {
  686. if (!control_socket_open || socket_ready_fd < 0) {
  687. return;
  688. }
  689. write(socket_ready_fd, control_socket_path, strlen(control_socket_path) + 1);
  690. // Once done with, close it (but leave stdout/stderr alone)
  691. if (socket_ready_fd > 2) {
  692. close(socket_ready_fd);
  693. }
  694. // Ensure that we don't try to issue readiness again:
  695. socket_ready_fd = -1;
  696. }
  697. // Callback when the root filesystem is read/write:
  698. void rootfs_is_rw() noexcept
  699. {
  700. if (!control_socket_open) {
  701. open_control_socket(true);
  702. control_socket_ready();
  703. }
  704. if (!did_log_boot) {
  705. did_log_boot = log_boot();
  706. }
  707. }
  708. // Open/create the control socket, normally /run/dinitctl, used to allow client programs to connect
  709. // and issue service orders and shutdown commands etc. This can safely be called multiple times;
  710. // once the socket has been successfully opened, further calls will check the socket file is still
  711. // present and re-create it if not.
  712. static bool open_control_socket(bool report_ro_failure) noexcept
  713. {
  714. if (control_socket_open) {
  715. struct stat stat_buf;
  716. if (stat(control_socket_path, &stat_buf) != 0 && errno == ENOENT) {
  717. // Looks like our control socket has disappeared from the filesystem. Close our control
  718. // socket and re-create it:
  719. control_socket_io.deregister(event_loop);
  720. close(control_socket_io.get_watched_fd());
  721. control_socket_open = false; // now re-open below
  722. }
  723. }
  724. if (!control_socket_open) {
  725. const char * saddrname = control_socket_path;
  726. size_t saddrname_len = strlen(saddrname);
  727. uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
  728. struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
  729. if (name == nullptr) {
  730. log(loglevel_t::ERROR, "Opening control socket: out of memory");
  731. return false;
  732. }
  733. name->sun_family = AF_UNIX;
  734. memcpy(name->sun_path, saddrname, saddrname_len + 1);
  735. int sockfd = dinit_socket(AF_UNIX, SOCK_STREAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
  736. if (sockfd == -1) {
  737. log(loglevel_t::ERROR, "Error creating control socket: ", strerror(errno));
  738. free(name);
  739. return false;
  740. }
  741. // Check if there is already an active control socket (from another instance).
  742. // Unfortunately, there's no way to check atomically if a socket file is stale. Still, we
  743. // will try to check, since the consequences of running a system dinit instance twice are
  744. // potentially severe.
  745. int connr = connect(sockfd, (struct sockaddr *) name, sockaddr_size);
  746. if (connr != -1 || errno == EAGAIN) {
  747. log(loglevel_t::ERROR, "Control socket is already active"
  748. " (another instance already running?)");
  749. close(connr);
  750. close(sockfd);
  751. free(name);
  752. return false;
  753. }
  754. // Unlink any stale control socket file.
  755. //
  756. // In the worst case, this potentially removes a socket which was not active at the time
  757. // we checked (just above) but has since become active; there's just no good API to avoid
  758. // this (we'd have to use a file lock, on yet another file). Since that's unlikely to
  759. // occur in practice, and because a stale socket will prevent communication with dinit (or
  760. // prevent it starting), then we'll take the chance on unlinking here.
  761. unlink(saddrname);
  762. if (bind(sockfd, (struct sockaddr *) name, sockaddr_size) == -1) {
  763. bool have_error = (errno != EROFS || report_ro_failure);
  764. if (have_error) {
  765. log(loglevel_t::ERROR, "Error binding control socket: ", strerror(errno));
  766. }
  767. close(sockfd);
  768. free(name);
  769. return !have_error;
  770. }
  771. free(name);
  772. // No connections can be made until we listen, so it is fine to change the permissions now
  773. // (and anyway there is no way to atomically create the socket and set permissions):
  774. if (chmod(saddrname, S_IRUSR | S_IWUSR) == -1) {
  775. log(loglevel_t::ERROR, "Error setting control socket permissions: ", strerror(errno));
  776. close(sockfd);
  777. return false;
  778. }
  779. if (listen(sockfd, 10) == -1) {
  780. log(loglevel_t::ERROR, "Error listening on control socket: ", strerror(errno));
  781. close(sockfd);
  782. return false;
  783. }
  784. try {
  785. control_socket_io.add_watch(event_loop, sockfd, dasynq::IN_EVENTS);
  786. control_socket_open = true;
  787. }
  788. catch (std::exception &e)
  789. {
  790. log(loglevel_t::ERROR, "Could not setup I/O on control socket: ", e.what());
  791. close(sockfd);
  792. }
  793. }
  794. return control_socket_open;
  795. }
  796. static void close_control_socket() noexcept
  797. {
  798. if (control_socket_open) {
  799. int fd = control_socket_io.get_watched_fd();
  800. control_socket_io.deregister(event_loop);
  801. close(fd);
  802. // Unlink the socket:
  803. unlink(control_socket_path);
  804. control_socket_open = false;
  805. }
  806. }
  807. void setup_external_log() noexcept
  808. {
  809. if (! external_log_open) {
  810. if (log_is_syslog) {
  811. const char * saddrname = log_path;
  812. size_t saddrname_len = strlen(saddrname);
  813. uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
  814. struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
  815. if (name == nullptr) {
  816. log(loglevel_t::ERROR, "Connecting to log socket: out of memory");
  817. return;
  818. }
  819. name->sun_family = AF_UNIX;
  820. memcpy(name->sun_path, saddrname, saddrname_len + 1);
  821. int sockfd = dinit_socket(AF_UNIX, SOCK_DGRAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
  822. if (sockfd == -1) {
  823. log(loglevel_t::ERROR, "Error creating log socket: ", strerror(errno));
  824. free(name);
  825. return;
  826. }
  827. if (connect(sockfd, (struct sockaddr *) name, sockaddr_size) == 0 || errno == EINPROGRESS) {
  828. // For EINPROGRESS, connection is still being established; however, we can select on
  829. // the file descriptor so we will be notified when it's ready. In other words we can
  830. // basically use it anyway.
  831. try {
  832. setup_main_log(sockfd);
  833. external_log_open = true;
  834. }
  835. catch (std::exception &e) {
  836. log(loglevel_t::ERROR, "Setting up log failed: ", e.what());
  837. close(sockfd);
  838. }
  839. }
  840. else {
  841. // Note if connect fails, we haven't warned at all, because the syslog server might not
  842. // have started yet.
  843. close(sockfd);
  844. }
  845. free(name);
  846. }
  847. else {
  848. // log to file:
  849. int log_fd = open(log_path, O_WRONLY | O_CREAT | O_APPEND | O_NONBLOCK | O_CLOEXEC, 0644);
  850. if (log_fd >= 0) {
  851. try {
  852. setup_main_log(log_fd);
  853. external_log_open = true;
  854. }
  855. catch (std::exception &e) {
  856. log(loglevel_t::ERROR, "Setting up log failed: ", e.what());
  857. close(log_fd);
  858. }
  859. }
  860. else {
  861. // log failure to log? It makes more sense than first appears, because we also log
  862. // to console:
  863. log(loglevel_t::ERROR, "Setting up log failed: ", strerror(errno));
  864. }
  865. }
  866. }
  867. }
  868. static void flush_log() noexcept
  869. {
  870. log_flush_timer.reset();
  871. log_flush_timer.arm_timer_rel(event_loop, timespec{5,0}); // 5 seconds
  872. while (!is_log_flushed() && !log_flush_timer.has_expired()) {
  873. event_loop.run();
  874. }
  875. }
  876. #ifdef SUPPORT_CGROUPS
  877. static void find_cgroup_path() noexcept
  878. {
  879. if (have_cgroups_path) {
  880. return;
  881. }
  882. int pfd = open("/proc/self/cgroup", O_RDONLY);
  883. if (pfd == -1) {
  884. return;
  885. }
  886. try {
  887. size_t cgroup_line_sz = 64;
  888. size_t cur_read = 0;
  889. size_t line_end_pos = (size_t)-1;
  890. size_t colon_count = 0; // how many colons have we seen?
  891. size_t second_colon_pos = 0;
  892. std::vector<char, default_init_allocator<char>> cgroup_line(cgroup_line_sz);
  893. while (true) {
  894. ssize_t r = read(pfd, cgroup_line.data() + cur_read, cgroup_line_sz - cur_read);
  895. if (r == 0) {
  896. if (line_end_pos == (size_t)-1) {
  897. line_end_pos = cur_read + 1;
  898. }
  899. break;
  900. }
  901. if (r == -1) {
  902. close(pfd);
  903. return;
  904. }
  905. size_t rr = (size_t)r;
  906. for (size_t i = 0; i < rr; ++i) {
  907. if (cgroup_line[cur_read + i] == '\n') {
  908. line_end_pos = cur_read + i;
  909. }
  910. else if (line_end_pos != (size_t)-1) {
  911. log(loglevel_t::WARN, "In multiple cgroups, cannot determine cgroup root path");
  912. close(pfd);
  913. return;
  914. }
  915. else if (cgroup_line[cur_read + i] == ':') {
  916. if (++colon_count == 2) {
  917. second_colon_pos = cur_read + i;
  918. }
  919. }
  920. }
  921. cur_read += rr;
  922. if (line_end_pos != (size_t)-1) {
  923. break;
  924. }
  925. if (cur_read == cgroup_line_sz) {
  926. cgroup_line.resize(cgroup_line_sz * 2);
  927. cgroup_line_sz *= 2;
  928. }
  929. };
  930. close(pfd);
  931. pfd = -1;
  932. // Now extract the path
  933. // The group line should look something like:
  934. //
  935. // 0::/some/path
  936. //
  937. // We want "some/path", i.e. we'll skip the leading slash.
  938. if (colon_count < 2 || (line_end_pos - second_colon_pos) == 1
  939. || cgroup_line[second_colon_pos+1] != '/') {
  940. // path is from 2nd colon to end
  941. log(loglevel_t::WARN, "Could not determine cgroup root path");
  942. return;
  943. }
  944. cgroups_path.clear();
  945. size_t first_char_pos = second_colon_pos + 2;
  946. size_t root_path_len = line_end_pos - first_char_pos;
  947. cgroups_path.append(cgroup_line.data() + first_char_pos, root_path_len);
  948. have_cgroups_path = true;
  949. return;
  950. }
  951. catch (std::bad_alloc &b) {
  952. if (pfd != -1) {
  953. close(pfd);
  954. }
  955. log(loglevel_t::WARN, "Out-of-memory reading cgroup root path");
  956. return;
  957. }
  958. }
  959. #endif // SUPPORT_CGROUPS
  960. static void printVersion()
  961. {
  962. std::cout << "Dinit version " << DINIT_VERSION << '.' << std::endl;
  963. const unsigned feature_count = 0
  964. #ifdef SUPPORT_CGROUPS
  965. +1
  966. #endif
  967. #ifdef USE_UTMPX
  968. +1
  969. #endif
  970. ;
  971. if (feature_count != 0) {
  972. std::cout << "Supported features:"
  973. #ifdef SUPPORT_CGROUPS
  974. " cgroups"
  975. #endif
  976. #ifdef USE_UTMPX
  977. " utmp"
  978. #endif
  979. "\n";
  980. }
  981. }
  982. /* handle SIGINT signal (generated by Linux kernel when ctrl+alt+del pressed) */
  983. static void sigint_reboot_cb(eventloop_t &eloop) noexcept
  984. {
  985. services->stop_all_services(shutdown_type_t::REBOOT);
  986. }
  987. /* handle SIGQUIT (if we are system init) */
  988. static void sigquit_cb(eventloop_t &eloop) noexcept
  989. {
  990. // This performs an immediate shutdown, without service rollback.
  991. close_control_socket();
  992. execl(shutdown_exec.c_str(), shutdown_exec.c_str(), "--system", (char *) 0);
  993. log(loglevel_t::ERROR, error_exec_sd, strerror(errno));
  994. sync(); // since a hard poweroff might be required at this point...
  995. }
  996. /* handle SIGTERM/SIGQUIT(non-system-daemon) - stop all services and shut down */
  997. static void sigterm_cb(eventloop_t &eloop) noexcept
  998. {
  999. services->stop_all_services();
  1000. }