daemonize.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. /*
  19. *
  20. * History:
  21. * --------
  22. * 2004-02-20 removed from ser main.c into its own file (andrei)
  23. * 2004-03-04 moved setuid/setgid in do_suid() (andrei)
  24. * 2004-03-25 added increase_open_fds & set_core_dump (andrei)
  25. * 2004-05-03 applied pgid patch from janakj
  26. * 2007-06-07 added mlock_pages (no swap) support (andrei)
  27. * added set_rt_prio() (andrei)
  28. */
  29. /*!
  30. * \file
  31. * \brief SIP-router core ::
  32. * \ingroup core
  33. * Module: \ref core
  34. */
  35. #include <sys/types.h>
  36. #define _XOPEN_SOURCE /*!< needed on linux for the getpgid prototype, but
  37. openbsd 3.2 won't include common types (uint a.s.o)
  38. if defined before including sys/types.h */
  39. #define _XOPEN_SOURCE_EXTENDED /*!< same as \ref _XOPEN_SOURCE */
  40. #define __USE_XOPEN_EXTENDED /*!< same as \ref _XOPEN_SOURCE, overrides features.h */
  41. #define __EXTENSIONS__ /*!< needed on solaris: if XOPEN_SOURCE is defined
  42. struct timeval defintion from <sys/time.h> won't
  43. be included => workarround define _EXTENSIONS_
  44. -andrei */
  45. #include <signal.h>
  46. #include <syslog.h>
  47. #include <errno.h>
  48. #include <string.h>
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <sys/time.h>
  52. #include <sys/resource.h> /* setrlimit */
  53. #include <unistd.h>
  54. #include <pwd.h>
  55. #include <grp.h>
  56. #ifdef HAVE_SCHED_SETSCHEDULER
  57. #include <sched.h>
  58. #endif
  59. #ifdef _POSIX_MEMLOCK
  60. #define HAVE_MLOCKALL
  61. #include <sys/mman.h>
  62. #endif
  63. #include "daemonize.h"
  64. #include "globals.h"
  65. #include "dprint.h"
  66. #include "signals.h"
  67. #include "cfg/cfg.h"
  68. #define MAX_FD 32 /* maximum number of inherited open file descriptors,
  69. (normally it shouldn't be bigger than 3) */
  70. /** temporary pipe FDs for sending exit status back to the ancestor process.
  71. * This pipe is used to send the desired exit status to the initial process,
  72. * that waits for it in the foreground. This way late errors preventing
  73. * startup (e.g. during modules child inits or TCP late init) can still be
  74. * reported back.
  75. */
  76. static int daemon_status_fd[2];
  77. /** init daemon status reporting.
  78. * Must be called before any other daemon_status function has a chance to
  79. * run.
  80. */
  81. void daemon_status_init()
  82. {
  83. daemon_status_fd[0] = -1;
  84. daemon_status_fd[1] = -1;
  85. }
  86. /** pre-daemonize init for daemon status reporting.
  87. * Must be called before forking.
  88. * Typically the parent process will call daemon_status_wait() while
  89. * one of the children will call daemon_status_send() at some point.
  90. *
  91. * @return 0 on success, -1 on error (and sets errno).
  92. */
  93. int daemon_status_pre_daemonize()
  94. {
  95. int ret;
  96. retry:
  97. ret = pipe(daemon_status_fd);
  98. if (ret < 0 && errno == EINTR)
  99. goto retry;
  100. return ret;
  101. }
  102. /** wait for an exit status to be send by daemon_status_send().
  103. * @param status - filled with the sent status (a char).
  104. * @return 0 on success, -1 on error (e.g. process died before sending
  105. * status, not intialized a.s.o.).
  106. * Side-effects: it will close the write side of the pipe
  107. * (must not be used from the same process as the daemon_status_send()).
  108. * Note: if init is not complete (only init, but no pre-daemonize)
  109. * it will return success always and status 0.
  110. */
  111. int daemon_status_wait(char* status)
  112. {
  113. int ret;
  114. /* close the output side of the pipe */
  115. if (daemon_status_fd[1] != -1) {
  116. close(daemon_status_fd[1]);
  117. daemon_status_fd[1] = -1;
  118. }
  119. if (daemon_status_fd[0] == -1) {
  120. *status = 0;
  121. return -1;
  122. }
  123. retry:
  124. ret = read(daemon_status_fd[0], status, 1);
  125. if (ret < 0 && errno == EINTR)
  126. goto retry;
  127. return (ret ==1 ) ? 0 : -1;
  128. }
  129. /** send 'status' to a waiting process running daemon_status_wait().
  130. * @param status - status byte
  131. * @return 0 on success, -1 on error.
  132. * Note: if init is not complete (only init, but no pre-daemonize)
  133. * it will return success always.
  134. */
  135. int daemon_status_send(char status)
  136. {
  137. int ret;
  138. if (daemon_status_fd[1] == -1)
  139. return 0;
  140. retry:
  141. ret = write(daemon_status_fd[1], &status, 1);
  142. if (ret < 0 && errno == EINTR)
  143. goto retry;
  144. return (ret ==1 ) ? 0 : -1;
  145. }
  146. /** cleanup functions for new processes.
  147. * Should be called after fork(), for each new process that _does_ _not_
  148. * use daemon_status_send() or daemon_status_wait().
  149. */
  150. void daemon_status_on_fork_cleanup()
  151. {
  152. if (daemon_status_fd[0] != -1) {
  153. close(daemon_status_fd[0]);
  154. daemon_status_fd[0] = -1;
  155. }
  156. if (daemon_status_fd[1] != -1) {
  157. close(daemon_status_fd[1]);
  158. daemon_status_fd[1] = -1;
  159. }
  160. }
  161. /** cleanup functions for processes that don't intead to wait.
  162. * Should be called after fork(), for each new process that doesn't
  163. * use daemon_status_wait().
  164. */
  165. void daemon_status_no_wait()
  166. {
  167. if (daemon_status_fd[0] != -1) {
  168. close(daemon_status_fd[0]);
  169. daemon_status_fd[0] = -1;
  170. }
  171. }
  172. /** daemon init.
  173. *@param name - daemon name used for logging (used when opening syslog).
  174. *@param status_wait - if 1 the original process will wait until it gets
  175. * an exit code send using daemon_status_send().
  176. *@return 0 in the child process (in case of daemonize mode),
  177. * -1 on error.
  178. * The original process that called daemonize() will be terminated if
  179. * dont_daemonize == 0. The exit code depends on status_wait. If status_wait
  180. * is non-zero, the original process will wait for a status code, that
  181. * must be sent with daemon_status_send() (daemon_status_send() must be
  182. * called or the original process will remain waiting until all the children
  183. * close()). If status_wait is 0, the original process will exit immediately
  184. * with exit(0).
  185. * Global variables/config params used:
  186. * dont_daemonize
  187. * chroot_dir
  188. * working_dir
  189. * pid_file - if set the pid will be written here (ascii).
  190. * pgid_file - if set, the pgid will be written here (ascii).
  191. * log_stderr - if not set syslog will be opened (openlog(name,...))
  192. *
  193. *
  194. * Side-effects:
  195. * sets own_pgid after becoming session leader (own process group).
  196. */
  197. int daemonize(char* name, int status_wait)
  198. {
  199. FILE *pid_stream;
  200. pid_t pid;
  201. int r, p;
  202. char pipe_status;
  203. p=-1;
  204. /* flush std file descriptors to avoid flushes after fork
  205. * (same message appearing multiple times)
  206. * and switch to unbuffered
  207. */
  208. setbuf(stdout, 0);
  209. setbuf(stderr, 0);
  210. if (chroot_dir&&(chroot(chroot_dir)<0)){
  211. LOG(L_CRIT, "Cannot chroot to %s: %s\n", chroot_dir, strerror(errno));
  212. goto error;
  213. }
  214. if (chdir(working_dir)<0){
  215. LOG(L_CRIT,"cannot chdir to %s: %s\n", working_dir, strerror(errno));
  216. goto error;
  217. }
  218. if (!dont_daemonize) {
  219. if (status_wait) {
  220. if (daemon_status_pre_daemonize() < 0)
  221. goto error;
  222. }
  223. /* fork to become!= group leader*/
  224. if ((pid=fork())<0){
  225. LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno));
  226. goto error;
  227. }else if (pid!=0){
  228. if (status_wait) {
  229. if (daemon_status_wait(&pipe_status) == 0)
  230. exit((int)pipe_status);
  231. else{
  232. LOG(L_ERR, "Main process exited before writing to pipe\n");
  233. exit(-1);
  234. }
  235. }
  236. exit(0);
  237. }
  238. if (status_wait)
  239. daemon_status_no_wait(); /* clean unused read fd */
  240. /* become session leader to drop the ctrl. terminal */
  241. if (setsid()<0){
  242. LOG(L_WARN, "setsid failed: %s\n",strerror(errno));
  243. }else{
  244. own_pgid=1;/* we have our own process group */
  245. }
  246. /* fork again to drop group leadership */
  247. if ((pid=fork())<0){
  248. LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno));
  249. goto error;
  250. }else if (pid!=0){
  251. /*parent process => exit */
  252. exit(0);
  253. }
  254. }
  255. /* added by noh: create a pid file for the main process */
  256. if (pid_file!=0){
  257. if ((pid_stream=fopen(pid_file, "r"))!=NULL){
  258. if (fscanf(pid_stream, "%d", &p) < 0) {
  259. LM_WARN("could not parse pid file %s\n", pid_file);
  260. }
  261. fclose(pid_stream);
  262. if (p==-1){
  263. LOG(L_CRIT, "pid file %s exists, but doesn't contain a valid"
  264. " pid number\n", pid_file);
  265. goto error;
  266. }
  267. if (kill((pid_t)p, 0)==0 || errno==EPERM){
  268. LOG(L_CRIT, "running process found in the pid file %s\n",
  269. pid_file);
  270. goto error;
  271. }else{
  272. LOG(L_WARN, "pid file contains old pid, replacing pid\n");
  273. }
  274. }
  275. pid=getpid();
  276. if ((pid_stream=fopen(pid_file, "w"))==NULL){
  277. LOG(L_WARN, "unable to create pid file %s: %s\n",
  278. pid_file, strerror(errno));
  279. goto error;
  280. }else{
  281. fprintf(pid_stream, "%i\n", (int)pid);
  282. fclose(pid_stream);
  283. }
  284. }
  285. if (pgid_file!=0){
  286. if ((pid_stream=fopen(pgid_file, "r"))!=NULL){
  287. if (fscanf(pid_stream, "%d", &p) < 0) {
  288. LM_WARN("could not parse pgid file %s\n", pgid_file);
  289. }
  290. fclose(pid_stream);
  291. if (p==-1){
  292. LOG(L_CRIT, "pgid file %s exists, but doesn't contain a valid"
  293. " pgid number\n", pgid_file);
  294. goto error;
  295. }
  296. }
  297. if (own_pgid){
  298. pid=getpgid(0);
  299. if ((pid_stream=fopen(pgid_file, "w"))==NULL){
  300. LOG(L_WARN, "unable to create pgid file %s: %s\n",
  301. pgid_file, strerror(errno));
  302. goto error;
  303. }else{
  304. fprintf(pid_stream, "%i\n", (int)pid);
  305. fclose(pid_stream);
  306. }
  307. }else{
  308. LOG(L_WARN, "we don't have our own process so we won't save"
  309. " our pgid\n");
  310. unlink(pgid_file); /* just to be sure nobody will miss-use the old
  311. value*/
  312. }
  313. }
  314. /* try to replace stdin, stdout & stderr with /dev/null */
  315. if (freopen("/dev/null", "r", stdin)==0){
  316. LOG(L_ERR, "unable to replace stdin with /dev/null: %s\n",
  317. strerror(errno));
  318. /* continue, leave it open */
  319. };
  320. if (freopen("/dev/null", "w", stdout)==0){
  321. LOG(L_ERR, "unable to replace stdout with /dev/null: %s\n",
  322. strerror(errno));
  323. /* continue, leave it open */
  324. };
  325. /* close stderr only if log_stderr=0 */
  326. if ((!log_stderr) &&(freopen("/dev/null", "w", stderr)==0)){
  327. LOG(L_ERR, "unable to replace stderr with /dev/null: %s\n",
  328. strerror(errno));
  329. /* continue, leave it open */
  330. };
  331. /* close all but the daemon_status_fd output as the main process
  332. must still write into it to tell the parent to exit with 0 */
  333. closelog();
  334. for (r=3;r<MAX_FD; r++){
  335. if(r != daemon_status_fd[1])
  336. close(r);
  337. }
  338. if (log_stderr==0)
  339. openlog(name, LOG_PID|LOG_CONS, cfg_get(core, core_cfg, log_facility));
  340. /* LOG_CONS, LOG_PERRROR ? */
  341. return 0;
  342. error:
  343. return -1;
  344. }
  345. int do_suid()
  346. {
  347. struct passwd *pw;
  348. if (gid){
  349. if(setgid(gid)<0){
  350. LOG(L_CRIT, "cannot change gid to %d: %s\n", gid, strerror(errno));
  351. goto error;
  352. }
  353. }
  354. if(uid){
  355. if (!(pw = getpwuid(uid))){
  356. LOG(L_CRIT, "user lookup failed: %s\n", strerror(errno));
  357. goto error;
  358. }
  359. if(initgroups(pw->pw_name, pw->pw_gid)<0){
  360. LOG(L_CRIT, "cannot set supplementary groups: %s\n",
  361. strerror(errno));
  362. goto error;
  363. }
  364. if(setuid(uid)<0){
  365. LOG(L_CRIT, "cannot change uid to %d: %s\n", uid, strerror(errno));
  366. goto error;
  367. }
  368. }
  369. return 0;
  370. error:
  371. return -1;
  372. }
  373. /*! \brief try to increase the open file limit */
  374. int increase_open_fds(int target)
  375. {
  376. struct rlimit lim;
  377. struct rlimit orig;
  378. if (getrlimit(RLIMIT_NOFILE, &lim)<0){
  379. LOG(L_CRIT, "cannot get the maximum number of file descriptors: %s\n",
  380. strerror(errno));
  381. goto error;
  382. }
  383. orig=lim;
  384. DBG("current open file limits: %lu/%lu\n",
  385. (unsigned long)lim.rlim_cur, (unsigned long)lim.rlim_max);
  386. if ((lim.rlim_cur==RLIM_INFINITY) || (target<=lim.rlim_cur))
  387. /* nothing to do */
  388. goto done;
  389. else if ((lim.rlim_max==RLIM_INFINITY) || (target<=lim.rlim_max)){
  390. lim.rlim_cur=target; /* increase soft limit to target */
  391. }else{
  392. /* more than the hard limit */
  393. LOG(L_INFO, "trying to increase the open file limit"
  394. " past the hard limit (%ld -> %d)\n",
  395. (unsigned long)lim.rlim_max, target);
  396. lim.rlim_max=target;
  397. lim.rlim_cur=target;
  398. }
  399. DBG("increasing open file limits to: %lu/%lu\n",
  400. (unsigned long)lim.rlim_cur, (unsigned long)lim.rlim_max);
  401. if (setrlimit(RLIMIT_NOFILE, &lim)<0){
  402. LOG(L_CRIT, "cannot increase the open file limit to"
  403. " %lu/%lu: %s\n",
  404. (unsigned long)lim.rlim_cur, (unsigned long)lim.rlim_max,
  405. strerror(errno));
  406. if (orig.rlim_max>orig.rlim_cur){
  407. /* try to increase to previous maximum, better than not increasing
  408. * at all */
  409. lim.rlim_max=orig.rlim_max;
  410. lim.rlim_cur=orig.rlim_max;
  411. if (setrlimit(RLIMIT_NOFILE, &lim)==0){
  412. LOG(L_CRIT, " maximum number of file descriptors increased to"
  413. " %u\n",(unsigned)orig.rlim_max);
  414. }
  415. }
  416. goto error;
  417. }
  418. done:
  419. return 0;
  420. error:
  421. return -1;
  422. }
  423. /*! \brief enable core dumps */
  424. int set_core_dump(int enable, int size)
  425. {
  426. struct rlimit lim;
  427. struct rlimit newlim;
  428. if (enable){
  429. if (getrlimit(RLIMIT_CORE, &lim)<0){
  430. LOG(L_CRIT, "cannot get the maximum core size: %s\n",
  431. strerror(errno));
  432. goto error;
  433. }
  434. if (lim.rlim_cur<size){
  435. /* first try max limits */
  436. newlim.rlim_max=RLIM_INFINITY;
  437. newlim.rlim_cur=newlim.rlim_max;
  438. if (setrlimit(RLIMIT_CORE, &newlim)==0) goto done;
  439. /* now try with size */
  440. if (lim.rlim_max<size){
  441. newlim.rlim_max=size;
  442. }
  443. newlim.rlim_cur=newlim.rlim_max;
  444. if (setrlimit(RLIMIT_CORE, &newlim)==0) goto done;
  445. /* if this failed too, try rlim_max, better than nothing */
  446. newlim.rlim_max=lim.rlim_max;
  447. newlim.rlim_cur=newlim.rlim_max;
  448. if (setrlimit(RLIMIT_CORE, &newlim)<0){
  449. LOG(L_CRIT, "could increase core limits at all: %s\n",
  450. strerror (errno));
  451. }else{
  452. LOG(L_CRIT, "core limits increased only to %lu\n",
  453. (unsigned long)lim.rlim_max);
  454. }
  455. goto error; /* it's an error we haven't got the size we wanted*/
  456. }
  457. goto done; /*nothing to do */
  458. }else{
  459. /* disable */
  460. newlim.rlim_cur=0;
  461. newlim.rlim_max=0;
  462. if (setrlimit(RLIMIT_CORE, &newlim)<0){
  463. LOG(L_CRIT, "failed to disable core dumps: %s\n",
  464. strerror(errno));
  465. goto error;
  466. }
  467. }
  468. done:
  469. DBG("core dump limits set to %lu\n", (unsigned long)newlim.rlim_cur);
  470. return 0;
  471. error:
  472. return -1;
  473. }
  474. /*! \brief lock pages in memory (make the process not swapable) */
  475. int mem_lock_pages()
  476. {
  477. #ifdef HAVE_MLOCKALL
  478. if (mlockall(MCL_CURRENT|MCL_FUTURE) !=0){
  479. LOG(L_WARN,"failed to lock the memory pages (disable swap): %s [%d]\n",
  480. strerror(errno), errno);
  481. goto error;
  482. }
  483. return 0;
  484. error:
  485. return -1;
  486. #else /* if MLOCKALL not defined return error */
  487. LOG(L_WARN,"failed to lock the memory pages: no mlockall support\n");
  488. return -1;
  489. #endif
  490. }
  491. /*! \brief tries to set real time priority
  492. * policy: 0 - SCHED_OTHER, 1 - SCHED_RR, 2 - SCHED_FIFO */
  493. int set_rt_prio(int prio, int policy)
  494. {
  495. #ifdef HAVE_SCHED_SETSCHEDULER
  496. struct sched_param sch_p;
  497. int min_prio, max_prio;
  498. int sched_policy;
  499. switch(policy){
  500. case 0:
  501. sched_policy=SCHED_OTHER;
  502. break;
  503. case 1:
  504. sched_policy=SCHED_RR;
  505. break;
  506. case 2:
  507. sched_policy=SCHED_FIFO;
  508. break;
  509. default:
  510. LOG(L_WARN, "WARNING: invalid scheduling policy,using"
  511. " SCHED_OTHER\n");
  512. sched_policy=SCHED_OTHER;
  513. }
  514. memset(&sch_p, 0, sizeof(sch_p));
  515. max_prio=sched_get_priority_max(policy);
  516. min_prio=sched_get_priority_min(policy);
  517. if (prio<min_prio){
  518. LOG(L_WARN, "scheduling priority %d too small, using minimum value"
  519. " (%d)\n", prio, min_prio);
  520. prio=min_prio;
  521. }else if (prio>max_prio){
  522. LOG(L_WARN, "scheduling priority %d too big, using maximum value"
  523. " (%d)\n", prio, max_prio);
  524. prio=max_prio;
  525. }
  526. sch_p.sched_priority=prio;
  527. if (sched_setscheduler(0, sched_policy, &sch_p) != 0){
  528. LOG(L_WARN, "could not switch to real time priority: %s [%d]\n",
  529. strerror(errno), errno);
  530. return -1;
  531. };
  532. return 0;
  533. #else
  534. LOG(L_WARN, "real time support not available\n");
  535. return -1;
  536. #endif
  537. }