pt.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. /*
  2. * $Id$
  3. *
  4. * Process Table
  5. *
  6. * Copyright (C) 2001-2003 FhG Fokus
  7. *
  8. * Permission to use, copy, modify, and distribute this software for any
  9. * purpose with or without fee is hereby granted, provided that the above
  10. * copyright notice and this permission notice appear in all copies.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  13. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  14. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  15. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  16. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  17. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  18. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19. */
  20. /*
  21. * History:
  22. * --------
  23. * 2006-06-14 added process table in shared mem (dragos)
  24. * 2006-09-20 added profile support (-DPROFILING) (hscholz)
  25. * 2006-10-25 sanity check before allowing forking w/ tcp support (is_main
  26. * & tcp not started yet); set is_main=0 in childs (andrei)
  27. * 2007-07-04 added register_fds() and get_max_open_fds(() (andrei)
  28. * 2010-08-19 use daemon_status_on_fork_cleanup() (andrei)
  29. */
  30. /** internal fork functions and process table.
  31. * @file: pt.c
  32. * @ingroup core
  33. */
  34. #include "pt.h"
  35. #include "tcp_init.h"
  36. #include "sr_module.h"
  37. #include "socket_info.h"
  38. #include "rand/fastrand.h"
  39. #ifdef PKG_MALLOC
  40. #include "mem/mem.h"
  41. #endif
  42. #ifdef SHM_MEM
  43. #include "mem/shm_mem.h"
  44. #endif
  45. #if defined PKG_MALLOC || defined SHM_MEM
  46. #include "cfg_core.h"
  47. #endif
  48. #include "daemonize.h"
  49. #include <stdio.h>
  50. #include <time.h> /* time(), used to initialize random numbers */
  51. #define FORK_DONT_WAIT /* child doesn't wait for parent before starting
  52. => faster startup, but the child should not assume
  53. the parent fixed the pt[] entry for it */
  54. #ifdef PROFILING
  55. #include <sys/gmon.h>
  56. extern void _start(void);
  57. extern void etext(void);
  58. #endif
  59. static int estimated_proc_no=0;
  60. static int estimated_fds_no=0;
  61. /* number of usec to wait before forking a process */
  62. static unsigned int fork_delay = 0;
  63. unsigned int set_fork_delay(unsigned int v)
  64. {
  65. unsigned int r;
  66. r = fork_delay;
  67. fork_delay = v;
  68. return r;
  69. }
  70. /* number of known "common" used fds */
  71. static int calc_common_open_fds_no(void)
  72. {
  73. int max_fds_no;
  74. /* 1 tcp send unix socket/all_proc,
  75. * + 1 udp sock/udp proc + 1 possible dns comm. socket +
  76. * + 1 temporary tcp send sock.
  77. * Per process:
  78. * + 1 if mhomed (now mhomed keeps a "cached socket" per process)
  79. * + 1 if mhomed & ipv6
  80. */
  81. max_fds_no=estimated_proc_no*4 /* udp|sctp + tcp unix sock +
  82. tmp. tcp send +
  83. tmp dns.*/
  84. -1 /* timer (no udp)*/ + 3 /* stdin/out/err */ +
  85. #ifdef USE_IPV6
  86. 2*mhomed
  87. #else
  88. mhomed
  89. #endif /* USE_IPV6*/
  90. ;
  91. return max_fds_no;
  92. }
  93. /* returns 0 on success, -1 on error */
  94. int init_pt(int proc_no)
  95. {
  96. #ifdef USE_TCP
  97. int r;
  98. #endif
  99. estimated_proc_no+=proc_no;
  100. estimated_fds_no+=calc_common_open_fds_no();
  101. /*alloc pids*/
  102. #ifdef SHM_MEM
  103. pt=shm_malloc(sizeof(struct process_table)*estimated_proc_no);
  104. process_count = shm_malloc(sizeof(int));
  105. #else
  106. pt=pkg_malloc(sizeof(struct process_table)*estimated_proc_no);
  107. process_count = pkg_malloc(sizeof(int));
  108. #endif
  109. process_lock = lock_alloc();
  110. process_lock = lock_init(process_lock);
  111. if (pt==0||process_count==0||process_lock==0){
  112. LOG(L_ERR, "ERROR: out of memory\n");
  113. return -1;
  114. }
  115. memset(pt, 0, sizeof(struct process_table)*estimated_proc_no);
  116. #ifdef USE_TCP
  117. for (r=0; r<estimated_proc_no; r++){
  118. pt[r].unix_sock=-1;
  119. pt[r].idx=-1;
  120. }
  121. #endif
  122. process_no=0; /*main process number*/
  123. pt[process_no].pid=getpid();
  124. memcpy(pt[process_no].desc,"main",5);
  125. *process_count=1;
  126. return 0;
  127. }
  128. /* register no processes, used from mod_init when processes will be forked
  129. * from mod_child
  130. * returns 0 on success, -1 on error
  131. */
  132. int register_procs(int no)
  133. {
  134. if (pt){
  135. LOG(L_CRIT, "BUG: register_procs(%d) called at runtime\n", no);
  136. return -1;
  137. }
  138. estimated_proc_no+=no;
  139. return 0;
  140. }
  141. /* returns the maximum number of processes */
  142. int get_max_procs()
  143. {
  144. if (pt==0){
  145. LOG(L_CRIT, "BUG: get_max_procs() called too early "
  146. "(it must _not_ be called from mod_init())\n");
  147. abort(); /* crash to quickly catch offenders */
  148. }
  149. return estimated_proc_no;
  150. }
  151. /* register no fds, used from mod_init when modules will open more global
  152. * fds (from mod_init or child_init(PROC_INIT)
  153. * or from child_init(rank) when the module will open fds local to the
  154. * process "rank".
  155. * (this is needed because some other parts of ser code rely on knowing
  156. * the maximum open fd number in a process)
  157. * returns 0 on success, -1 on error
  158. */
  159. int register_fds(int no)
  160. {
  161. /* can be called at runtime, but should be called from child_init() */
  162. estimated_fds_no+=no;
  163. return 0;
  164. }
  165. /* returns the maximum open fd number */
  166. int get_max_open_fds()
  167. {
  168. if (pt==0){
  169. LOG(L_CRIT, "BUG: get_max_open_fds() called too early "
  170. "(it must _not_ be called from mod_init())\n");
  171. abort(); /* crash to quickly catch offenders */
  172. }
  173. return estimated_fds_no;
  174. }
  175. /* return processes pid */
  176. int my_pid()
  177. {
  178. return pt ? pt[process_no].pid : getpid();
  179. }
  180. /* close unneeded sockets */
  181. int close_extra_socks(int child_id, int proc_no)
  182. {
  183. #ifdef USE_TCP
  184. int r;
  185. struct socket_info* si;
  186. if (child_id!=PROC_TCP_MAIN){
  187. for (r=0; r<proc_no; r++){
  188. if (pt[r].unix_sock>=0){
  189. /* we can't change the value in pt[] because it's
  190. * shared so we only close it */
  191. close(pt[r].unix_sock);
  192. }
  193. }
  194. /* close all listen sockets (needed only in tcp_main */
  195. if (!tcp_disable){
  196. for(si=tcp_listen; si; si=si->next){
  197. close(si->socket);
  198. /* safe to change since this is a per process copy */
  199. si->socket=-1;
  200. }
  201. #ifdef USE_TLS
  202. if (!tls_disable){
  203. for(si=tls_listen; si; si=si->next){
  204. close(si->socket);
  205. /* safe to change since this is a per process copy */
  206. si->socket=-1;
  207. }
  208. }
  209. #endif /* USE_TLS */
  210. }
  211. /* we still need the udp sockets (for sending) so we don't close them
  212. * too */
  213. }
  214. #endif /* USE_TCP */
  215. return 0;
  216. }
  217. /**
  218. * Forks a new process.
  219. * @param child_id - rank, if equal to PROC_NOCHLDINIT init_child will not be
  220. * called for the new forked process (see sr_module.h)
  221. * @param desc - text description for the process table
  222. * @param make_sock - if to create a unix socket pair for it
  223. * @returns the pid of the new process
  224. */
  225. int fork_process(int child_id, char *desc, int make_sock)
  226. {
  227. int pid, child_process_no;
  228. int ret;
  229. unsigned int new_seed1;
  230. unsigned int new_seed2;
  231. #ifdef USE_TCP
  232. int sockfd[2];
  233. #endif
  234. if(unlikely(fork_delay>0))
  235. sleep_us(fork_delay);
  236. ret=-1;
  237. #ifdef USE_TCP
  238. sockfd[0]=sockfd[1]=-1;
  239. if(make_sock && !tcp_disable){
  240. if (!is_main){
  241. LOG(L_CRIT, "BUG: fork_process(..., 1) called from a non "
  242. "\"main\" process! If forking from a module's "
  243. "child_init() fork only if rank==PROC_MAIN or"
  244. " give up tcp send support (use 0 for make_sock)\n");
  245. goto error;
  246. }
  247. if (tcp_main_pid){
  248. LOG(L_CRIT, "BUG: fork_process(..., 1) called, but tcp main "
  249. " is already started\n");
  250. goto error;
  251. }
  252. if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
  253. LOG(L_ERR, "ERROR: fork_process(): socketpair failed: %s\n",
  254. strerror(errno));
  255. goto error;
  256. }
  257. }
  258. #endif
  259. lock_get(process_lock);
  260. if (*process_count>=estimated_proc_no) {
  261. LOG(L_CRIT, "ERROR: fork_process(): Process limit of %d exceeded."
  262. " Will simulate fork fail.\n", estimated_proc_no);
  263. lock_release(process_lock);
  264. goto error;
  265. }
  266. child_process_no = *process_count;
  267. new_seed1=rand();
  268. new_seed2=random();
  269. pid = fork();
  270. if (pid<0) {
  271. lock_release(process_lock);
  272. ret=pid;
  273. goto error;
  274. }else if (pid==0){
  275. /* child */
  276. is_main=0; /* a forked process cannot be the "main" one */
  277. process_no=child_process_no;
  278. daemon_status_on_fork_cleanup();
  279. /* close tcp unix sockets if this is not tcp main */
  280. #ifdef USE_TCP
  281. close_extra_socks(child_id, process_no);
  282. #endif /* USE_TCP */
  283. srand(new_seed1);
  284. fastrand_seed(rand());
  285. srandom(new_seed2+time(0));
  286. shm_malloc_on_fork();
  287. #ifdef PROFILING
  288. monstartup((u_long) &_start, (u_long) &etext);
  289. #endif
  290. #ifdef FORK_DONT_WAIT
  291. /* record pid twice to avoid the child using it, before
  292. * parent gets a chance to set it*/
  293. pt[process_no].pid=getpid();
  294. #else
  295. /* wait for parent to get out of critical zone.
  296. * this is actually relevant as the parent updates
  297. * the pt & process_count. */
  298. lock_get(process_lock);
  299. lock_release(process_lock);
  300. #endif
  301. #ifdef USE_TCP
  302. if (make_sock && !tcp_disable){
  303. close(sockfd[0]);
  304. unix_tcp_sock=sockfd[1];
  305. }
  306. #endif
  307. if ((child_id!=PROC_NOCHLDINIT) && (init_child(child_id) < 0)) {
  308. LOG(L_ERR, "ERROR: fork_process(): init_child failed for "
  309. " process %d, pid %d, \"%s\"\n", process_no,
  310. pt[process_no].pid, pt[process_no].desc);
  311. return -1;
  312. }
  313. return pid;
  314. } else {
  315. /* parent */
  316. (*process_count)++;
  317. #ifdef FORK_DONT_WAIT
  318. lock_release(process_lock);
  319. #endif
  320. /* add the process to the list in shm */
  321. pt[child_process_no].pid=pid;
  322. if (desc){
  323. strncpy(pt[child_process_no].desc, desc, MAX_PT_DESC);
  324. }
  325. #ifdef USE_TCP
  326. if (make_sock && !tcp_disable){
  327. close(sockfd[1]);
  328. pt[child_process_no].unix_sock=sockfd[0];
  329. pt[child_process_no].idx=-1; /* this is not a "tcp" process*/
  330. }
  331. #endif
  332. #ifdef FORK_DONT_WAIT
  333. #else
  334. lock_release(process_lock);
  335. #endif
  336. ret=pid;
  337. goto end;
  338. }
  339. error:
  340. #ifdef USE_TCP
  341. if (sockfd[0]!=-1) close(sockfd[0]);
  342. if (sockfd[1]!=-1) close(sockfd[1]);
  343. #endif
  344. end:
  345. return ret;
  346. }
  347. /**
  348. * Forks a new TCP process.
  349. * @param desc - text description for the process table
  350. * @param r - index in the tcp_children array
  351. * @param *reader_fd_1 - pointer to return the reader_fd[1]
  352. * @returns the pid of the new process
  353. */
  354. #ifdef USE_TCP
  355. int fork_tcp_process(int child_id, char *desc, int r, int *reader_fd_1)
  356. {
  357. int pid, child_process_no;
  358. int sockfd[2];
  359. int reader_fd[2]; /* for comm. with the tcp children read */
  360. int ret;
  361. int i;
  362. unsigned int new_seed1;
  363. unsigned int new_seed2;
  364. /* init */
  365. sockfd[0]=sockfd[1]=-1;
  366. reader_fd[0]=reader_fd[1]=-1;
  367. ret=-1;
  368. if (!is_main){
  369. LOG(L_CRIT, "BUG: fork_tcp_process() called from a non \"main\" "
  370. "process\n");
  371. goto error;
  372. }
  373. if (tcp_main_pid){
  374. LOG(L_CRIT, "BUG: fork_tcp_process(..., 1) called _after_ starting"
  375. " tcp main\n");
  376. goto error;
  377. }
  378. if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
  379. LOG(L_ERR, "ERROR: fork_tcp_process(): socketpair failed: %s\n",
  380. strerror(errno));
  381. goto error;
  382. }
  383. if (socketpair(AF_UNIX, SOCK_STREAM, 0, reader_fd)<0){
  384. LOG(L_ERR, "ERROR: fork_tcp_process(): socketpair failed: %s\n",
  385. strerror(errno));
  386. goto error;
  387. }
  388. if (tcp_fix_child_sockets(reader_fd)<0){
  389. LOG(L_ERR, "ERROR: fork_tcp_process(): failed to set non blocking"
  390. "on child sockets\n");
  391. /* continue, it's not critical (it will go slower under
  392. * very high connection rates) */
  393. }
  394. lock_get(process_lock);
  395. /* set the local process_no */
  396. if (*process_count>=estimated_proc_no) {
  397. LOG(L_CRIT, "ERROR: fork_tcp_process(): Process limit of %d exceeded."
  398. " Simulating fork fail\n", estimated_proc_no);
  399. lock_release(process_lock);
  400. goto error;
  401. }
  402. child_process_no = *process_count;
  403. new_seed1=rand();
  404. new_seed2=random();
  405. pid = fork();
  406. if (pid<0) {
  407. lock_release(process_lock);
  408. ret=pid;
  409. goto end;
  410. }
  411. if (pid==0){
  412. is_main=0; /* a forked process cannot be the "main" one */
  413. process_no=child_process_no;
  414. /* close unneeded unix sockets */
  415. close_extra_socks(child_id, process_no);
  416. /* same for unneeded tcp_children <-> tcp_main unix socks */
  417. for (i=0; i<r; i++){
  418. if (tcp_children[i].unix_sock>=0){
  419. close(tcp_children[i].unix_sock);
  420. /* tcp_children is per process, so it's safe to change
  421. * the unix_sock to -1 */
  422. tcp_children[i].unix_sock=-1;
  423. }
  424. }
  425. daemon_status_on_fork_cleanup();
  426. srand(new_seed1);
  427. fastrand_seed(rand());
  428. srandom(new_seed2+time(0));
  429. shm_malloc_on_fork();
  430. #ifdef PROFILING
  431. monstartup((u_long) &_start, (u_long) &etext);
  432. #endif
  433. #ifdef FORK_DONT_WAIT
  434. /* record pid twice to avoid the child using it, before
  435. - * parent gets a chance to set it*/
  436. pt[process_no].pid=getpid();
  437. #else
  438. /* wait for parent to get out of critical zone */
  439. lock_get(process_lock);
  440. lock_release(process_lock);
  441. #endif
  442. close(sockfd[0]);
  443. unix_tcp_sock=sockfd[1];
  444. close(reader_fd[0]);
  445. if (reader_fd_1) *reader_fd_1=reader_fd[1];
  446. if ((child_id!=PROC_NOCHLDINIT) && (init_child(child_id) < 0)) {
  447. LOG(L_ERR, "ERROR: fork_tcp_process(): init_child failed for "
  448. "process %d, pid %d, \"%s\"\n", process_no,
  449. pt[process_no].pid, pt[process_no].desc);
  450. return -1;
  451. }
  452. return pid;
  453. } else {
  454. /* parent */
  455. (*process_count)++;
  456. #ifdef FORK_DONT_WAIT
  457. lock_release(process_lock);
  458. #endif
  459. /* add the process to the list in shm */
  460. pt[child_process_no].pid=pid;
  461. pt[child_process_no].unix_sock=sockfd[0];
  462. pt[child_process_no].idx=r;
  463. if (desc){
  464. snprintf(pt[child_process_no].desc, MAX_PT_DESC, "%s child=%d",
  465. desc, r);
  466. }
  467. #ifdef FORK_DONT_WAIT
  468. #else
  469. lock_release(process_lock);
  470. #endif
  471. close(sockfd[1]);
  472. close(reader_fd[1]);
  473. tcp_children[r].pid=pid;
  474. tcp_children[r].proc_no=child_process_no;
  475. tcp_children[r].busy=0;
  476. tcp_children[r].n_reqs=0;
  477. tcp_children[r].unix_sock=reader_fd[0];
  478. ret=pid;
  479. goto end;
  480. }
  481. error:
  482. if (sockfd[0]!=-1) close(sockfd[0]);
  483. if (sockfd[1]!=-1) close(sockfd[1]);
  484. if (reader_fd[0]!=-1) close(reader_fd[0]);
  485. if (reader_fd[1]!=-1) close(reader_fd[1]);
  486. end:
  487. return ret;
  488. }
  489. #endif
  490. #ifdef PKG_MALLOC
  491. /* Dumps pkg memory status.
  492. * Per-child process callback that is called
  493. * when mem_dump_pkg cfg var is changed.
  494. */
  495. void mem_dump_pkg_cb(str *gname, str *name)
  496. {
  497. int old_memlog;
  498. int memlog;
  499. if (cfg_get(core, core_cfg, mem_dump_pkg) == my_pid()) {
  500. /* set memlog to ALERT level to force
  501. printing the log messages */
  502. old_memlog = cfg_get(core, core_cfg, memlog);
  503. memlog = L_ALERT;
  504. /* ugly hack to temporarily switch memlog to something visible,
  505. possible race with a parallel cfg_set */
  506. ((struct cfg_group_core*)core_cfg)->memlog=memlog;
  507. LOG(memlog, "Memory status (pkg) of process %d:\n", my_pid());
  508. pkg_status();
  509. ((struct cfg_group_core*)core_cfg)->memlog=old_memlog;
  510. }
  511. }
  512. #endif
  513. #ifdef SHM_MEM
  514. /* Dumps shm memory status.
  515. * fixup function that is called
  516. * when mem_dump_shm cfg var is set.
  517. */
  518. int mem_dump_shm_fixup(void *handle, str *gname, str *name, void **val)
  519. {
  520. int old_memlog;
  521. int memlog;
  522. if ((long)(void*)(*val)) {
  523. /* set memlog to ALERT level to force
  524. printing the log messages */
  525. old_memlog = cfg_get(core, core_cfg, memlog);
  526. memlog = L_ALERT;
  527. /* ugly hack to temporarily switch memlog to something visible,
  528. possible race with a parallel cfg_set */
  529. ((struct cfg_group_core*)core_cfg)->memlog=memlog;
  530. LOG(memlog, "Memory status (shm)\n");
  531. shm_status();
  532. ((struct cfg_group_core*)core_cfg)->memlog=old_memlog;
  533. *val = (void*)(long)0;
  534. }
  535. return 0;
  536. }
  537. #endif