dinit.cc 42 KB

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