pt.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  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. 2*mhomed
  86. ;
  87. return max_fds_no;
  88. }
  89. /* returns 0 on success, -1 on error */
  90. int init_pt(int proc_no)
  91. {
  92. #ifdef USE_TCP
  93. int r;
  94. #endif
  95. estimated_proc_no+=proc_no;
  96. estimated_fds_no+=calc_common_open_fds_no();
  97. /*alloc pids*/
  98. #ifdef SHM_MEM
  99. pt=shm_malloc(sizeof(struct process_table)*estimated_proc_no);
  100. process_count = shm_malloc(sizeof(int));
  101. #else
  102. pt=pkg_malloc(sizeof(struct process_table)*estimated_proc_no);
  103. process_count = pkg_malloc(sizeof(int));
  104. #endif
  105. process_lock = lock_alloc();
  106. process_lock = lock_init(process_lock);
  107. if (pt==0||process_count==0||process_lock==0){
  108. LM_ERR("out of memory\n");
  109. return -1;
  110. }
  111. memset(pt, 0, sizeof(struct process_table)*estimated_proc_no);
  112. #ifdef USE_TCP
  113. for (r=0; r<estimated_proc_no; r++){
  114. pt[r].unix_sock=-1;
  115. pt[r].idx=-1;
  116. }
  117. #endif
  118. process_no=0; /*main process number*/
  119. pt[process_no].pid=getpid();
  120. memcpy(pt[process_no].desc,"main",5);
  121. *process_count=1;
  122. return 0;
  123. }
  124. /* register no processes, used from mod_init when processes will be forked
  125. * from mod_child
  126. * returns 0 on success, -1 on error
  127. */
  128. int register_procs(int no)
  129. {
  130. if (pt){
  131. LM_CRIT("(%d) called at runtime\n", no);
  132. return -1;
  133. }
  134. estimated_proc_no+=no;
  135. return 0;
  136. }
  137. /* returns the maximum number of processes */
  138. int get_max_procs()
  139. {
  140. if (pt==0){
  141. LM_CRIT("too early (it must _not_ be called from mod_init())\n");
  142. abort(); /* crash to quickly catch offenders */
  143. }
  144. return estimated_proc_no;
  145. }
  146. /* register no fds, used from mod_init when modules will open more global
  147. * fds (from mod_init or child_init(PROC_INIT)
  148. * or from child_init(rank) when the module will open fds local to the
  149. * process "rank".
  150. * (this is needed because some other parts of ser code rely on knowing
  151. * the maximum open fd number in a process)
  152. * returns 0 on success, -1 on error
  153. */
  154. int register_fds(int no)
  155. {
  156. /* can be called at runtime, but should be called from child_init() */
  157. estimated_fds_no+=no;
  158. return 0;
  159. }
  160. /* returns the maximum open fd number */
  161. int get_max_open_fds()
  162. {
  163. if (pt==0){
  164. LM_CRIT("too early (it must _not_ be called from mod_init())\n");
  165. abort(); /* crash to quickly catch offenders */
  166. }
  167. return estimated_fds_no;
  168. }
  169. /* return processes pid */
  170. int my_pid()
  171. {
  172. return pt ? pt[process_no].pid : getpid();
  173. }
  174. /* close unneeded sockets */
  175. int close_extra_socks(int child_id, int proc_no)
  176. {
  177. #ifdef USE_TCP
  178. int r;
  179. struct socket_info* si;
  180. if (child_id!=PROC_TCP_MAIN){
  181. for (r=0; r<proc_no; r++){
  182. if (pt[r].unix_sock>=0){
  183. /* we can't change the value in pt[] because it's
  184. * shared so we only close it */
  185. close(pt[r].unix_sock);
  186. }
  187. }
  188. /* close all listen sockets (needed only in tcp_main */
  189. if (!tcp_disable){
  190. for(si=tcp_listen; si; si=si->next){
  191. close(si->socket);
  192. /* safe to change since this is a per process copy */
  193. si->socket=-1;
  194. }
  195. #ifdef USE_TLS
  196. if (!tls_disable){
  197. for(si=tls_listen; si; si=si->next){
  198. close(si->socket);
  199. /* safe to change since this is a per process copy */
  200. si->socket=-1;
  201. }
  202. }
  203. #endif /* USE_TLS */
  204. }
  205. /* we still need the udp sockets (for sending) so we don't close them
  206. * too */
  207. }
  208. #endif /* USE_TCP */
  209. return 0;
  210. }
  211. /**
  212. * Forks a new process.
  213. * @param child_id - rank, if equal to PROC_NOCHLDINIT init_child will not be
  214. * called for the new forked process (see sr_module.h)
  215. * @param desc - text description for the process table
  216. * @param make_sock - if to create a unix socket pair for it
  217. * @returns the pid of the new process
  218. */
  219. int fork_process(int child_id, char *desc, int make_sock)
  220. {
  221. int pid, child_process_no;
  222. int ret;
  223. unsigned int new_seed1;
  224. unsigned int new_seed2;
  225. #ifdef USE_TCP
  226. int sockfd[2];
  227. #endif
  228. if(unlikely(fork_delay>0))
  229. sleep_us(fork_delay);
  230. ret=-1;
  231. #ifdef USE_TCP
  232. sockfd[0]=sockfd[1]=-1;
  233. if(make_sock && !tcp_disable){
  234. if (!is_main){
  235. LM_CRIT("called from a non "
  236. "\"main\" process! If forking from a module's "
  237. "child_init() fork only if rank==PROC_MAIN or"
  238. " give up tcp send support (use 0 for make_sock)\n");
  239. goto error;
  240. }
  241. if (tcp_main_pid){
  242. LM_CRIT("called, but tcp main is already started\n");
  243. goto error;
  244. }
  245. if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
  246. LM_ERR("socketpair failed: %s\n",
  247. strerror(errno));
  248. goto error;
  249. }
  250. }
  251. #endif
  252. lock_get(process_lock);
  253. if (*process_count>=estimated_proc_no) {
  254. LM_CRIT("Process limit of %d exceeded. Will simulate fork fail.\n", estimated_proc_no);
  255. lock_release(process_lock);
  256. goto error;
  257. }
  258. child_process_no = *process_count;
  259. new_seed1=rand();
  260. new_seed2=random();
  261. pid = fork();
  262. if (pid<0) {
  263. lock_release(process_lock);
  264. ret=pid;
  265. goto error;
  266. }else if (pid==0){
  267. /* child */
  268. is_main=0; /* a forked process cannot be the "main" one */
  269. process_no=child_process_no;
  270. daemon_status_on_fork_cleanup();
  271. /* close tcp unix sockets if this is not tcp main */
  272. #ifdef USE_TCP
  273. close_extra_socks(child_id, process_no);
  274. #endif /* USE_TCP */
  275. srand(new_seed1);
  276. fastrand_seed(rand());
  277. srandom(new_seed2+time(0));
  278. shm_malloc_on_fork();
  279. #ifdef PROFILING
  280. monstartup((u_long) &_start, (u_long) &etext);
  281. #endif
  282. #ifdef FORK_DONT_WAIT
  283. /* record pid twice to avoid the child using it, before
  284. * parent gets a chance to set it*/
  285. pt[process_no].pid=getpid();
  286. #else
  287. /* wait for parent to get out of critical zone.
  288. * this is actually relevant as the parent updates
  289. * the pt & process_count. */
  290. lock_get(process_lock);
  291. lock_release(process_lock);
  292. #endif
  293. #ifdef USE_TCP
  294. if (make_sock && !tcp_disable){
  295. close(sockfd[0]);
  296. unix_tcp_sock=sockfd[1];
  297. }
  298. #endif
  299. if ((child_id!=PROC_NOCHLDINIT) && (init_child(child_id) < 0)) {
  300. LM_ERR("init_child failed for process %d, pid %d, \"%s\"\n",
  301. process_no, pt[process_no].pid, pt[process_no].desc);
  302. return -1;
  303. }
  304. return pid;
  305. } else {
  306. /* parent */
  307. (*process_count)++;
  308. #ifdef FORK_DONT_WAIT
  309. lock_release(process_lock);
  310. #endif
  311. /* add the process to the list in shm */
  312. pt[child_process_no].pid=pid;
  313. if (desc){
  314. strncpy(pt[child_process_no].desc, desc, MAX_PT_DESC);
  315. }
  316. #ifdef USE_TCP
  317. if (make_sock && !tcp_disable){
  318. close(sockfd[1]);
  319. pt[child_process_no].unix_sock=sockfd[0];
  320. pt[child_process_no].idx=-1; /* this is not a "tcp" process*/
  321. }
  322. #endif
  323. #ifdef FORK_DONT_WAIT
  324. #else
  325. lock_release(process_lock);
  326. #endif
  327. ret=pid;
  328. goto end;
  329. }
  330. error:
  331. #ifdef USE_TCP
  332. if (sockfd[0]!=-1) close(sockfd[0]);
  333. if (sockfd[1]!=-1) close(sockfd[1]);
  334. #endif
  335. end:
  336. return ret;
  337. }
  338. /**
  339. * Forks a new TCP process.
  340. * @param desc - text description for the process table
  341. * @param r - index in the tcp_children array
  342. * @param *reader_fd_1 - pointer to return the reader_fd[1]
  343. * @returns the pid of the new process
  344. */
  345. #ifdef USE_TCP
  346. int fork_tcp_process(int child_id, char *desc, int r, int *reader_fd_1)
  347. {
  348. int pid, child_process_no;
  349. int sockfd[2];
  350. int reader_fd[2]; /* for comm. with the tcp children read */
  351. int ret;
  352. int i;
  353. unsigned int new_seed1;
  354. unsigned int new_seed2;
  355. /* init */
  356. sockfd[0]=sockfd[1]=-1;
  357. reader_fd[0]=reader_fd[1]=-1;
  358. ret=-1;
  359. if (!is_main){
  360. LM_CRIT("called from a non \"main\" process\n");
  361. goto error;
  362. }
  363. if (tcp_main_pid){
  364. LM_CRIT("called _after_ starting tcp main\n");
  365. goto error;
  366. }
  367. if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
  368. LM_ERR("socketpair failed: %s\n", strerror(errno));
  369. goto error;
  370. }
  371. if (socketpair(AF_UNIX, SOCK_STREAM, 0, reader_fd)<0){
  372. LM_ERR("socketpair failed: %s\n", strerror(errno));
  373. goto error;
  374. }
  375. if (tcp_fix_child_sockets(reader_fd)<0){
  376. LM_ERR("failed to set non blocking on child sockets\n");
  377. /* continue, it's not critical (it will go slower under
  378. * very high connection rates) */
  379. }
  380. lock_get(process_lock);
  381. /* set the local process_no */
  382. if (*process_count>=estimated_proc_no) {
  383. LM_CRIT("Process limit of %d exceeded. Simulating fork fail\n",
  384. estimated_proc_no);
  385. lock_release(process_lock);
  386. goto error;
  387. }
  388. child_process_no = *process_count;
  389. new_seed1=rand();
  390. new_seed2=random();
  391. pid = fork();
  392. if (pid<0) {
  393. lock_release(process_lock);
  394. ret=pid;
  395. goto end;
  396. }
  397. if (pid==0){
  398. is_main=0; /* a forked process cannot be the "main" one */
  399. process_no=child_process_no;
  400. /* close unneeded unix sockets */
  401. close_extra_socks(child_id, process_no);
  402. /* same for unneeded tcp_children <-> tcp_main unix socks */
  403. for (i=0; i<r; i++){
  404. if (tcp_children[i].unix_sock>=0){
  405. close(tcp_children[i].unix_sock);
  406. /* tcp_children is per process, so it's safe to change
  407. * the unix_sock to -1 */
  408. tcp_children[i].unix_sock=-1;
  409. }
  410. }
  411. daemon_status_on_fork_cleanup();
  412. srand(new_seed1);
  413. fastrand_seed(rand());
  414. srandom(new_seed2+time(0));
  415. shm_malloc_on_fork();
  416. #ifdef PROFILING
  417. monstartup((u_long) &_start, (u_long) &etext);
  418. #endif
  419. #ifdef FORK_DONT_WAIT
  420. /* record pid twice to avoid the child using it, before
  421. - * parent gets a chance to set it*/
  422. pt[process_no].pid=getpid();
  423. #else
  424. /* wait for parent to get out of critical zone */
  425. lock_get(process_lock);
  426. lock_release(process_lock);
  427. #endif
  428. close(sockfd[0]);
  429. unix_tcp_sock=sockfd[1];
  430. close(reader_fd[0]);
  431. if (reader_fd_1) *reader_fd_1=reader_fd[1];
  432. if ((child_id!=PROC_NOCHLDINIT) && (init_child(child_id) < 0)) {
  433. LM_ERR("init_child failed for process %d, pid %d, \"%s\"\n",
  434. process_no, pt[process_no].pid, pt[process_no].desc);
  435. return -1;
  436. }
  437. return pid;
  438. } else {
  439. /* parent */
  440. (*process_count)++;
  441. #ifdef FORK_DONT_WAIT
  442. lock_release(process_lock);
  443. #endif
  444. /* add the process to the list in shm */
  445. pt[child_process_no].pid=pid;
  446. pt[child_process_no].unix_sock=sockfd[0];
  447. pt[child_process_no].idx=r;
  448. if (desc){
  449. snprintf(pt[child_process_no].desc, MAX_PT_DESC, "%s child=%d",
  450. desc, r);
  451. }
  452. #ifdef FORK_DONT_WAIT
  453. #else
  454. lock_release(process_lock);
  455. #endif
  456. close(sockfd[1]);
  457. close(reader_fd[1]);
  458. tcp_children[r].pid=pid;
  459. tcp_children[r].proc_no=child_process_no;
  460. tcp_children[r].busy=0;
  461. tcp_children[r].n_reqs=0;
  462. tcp_children[r].unix_sock=reader_fd[0];
  463. ret=pid;
  464. goto end;
  465. }
  466. error:
  467. if (sockfd[0]!=-1) close(sockfd[0]);
  468. if (sockfd[1]!=-1) close(sockfd[1]);
  469. if (reader_fd[0]!=-1) close(reader_fd[0]);
  470. if (reader_fd[1]!=-1) close(reader_fd[1]);
  471. end:
  472. return ret;
  473. }
  474. #endif
  475. #ifdef PKG_MALLOC
  476. /* Dumps pkg memory status.
  477. * Per-child process callback that is called
  478. * when mem_dump_pkg cfg var is changed.
  479. */
  480. void mem_dump_pkg_cb(str *gname, str *name)
  481. {
  482. int old_memlog;
  483. int memlog;
  484. if (cfg_get(core, core_cfg, mem_dump_pkg) == my_pid()) {
  485. /* set memlog to ALERT level to force
  486. printing the log messages */
  487. old_memlog = cfg_get(core, core_cfg, memlog);
  488. memlog = L_ALERT;
  489. /* ugly hack to temporarily switch memlog to something visible,
  490. possible race with a parallel cfg_set */
  491. ((struct cfg_group_core*)core_cfg)->memlog=memlog;
  492. LOG(memlog, "Memory status (pkg) of process %d:\n", my_pid());
  493. pkg_status();
  494. ((struct cfg_group_core*)core_cfg)->memlog=old_memlog;
  495. }
  496. }
  497. #endif
  498. #ifdef SHM_MEM
  499. /* Dumps shm memory status.
  500. * fixup function that is called
  501. * when mem_dump_shm cfg var is set.
  502. */
  503. int mem_dump_shm_fixup(void *handle, str *gname, str *name, void **val)
  504. {
  505. int old_memlog;
  506. int memlog;
  507. if ((long)(void*)(*val)) {
  508. /* set memlog to ALERT level to force
  509. printing the log messages */
  510. old_memlog = cfg_get(core, core_cfg, memlog);
  511. memlog = L_ALERT;
  512. /* ugly hack to temporarily switch memlog to something visible,
  513. possible race with a parallel cfg_set */
  514. ((struct cfg_group_core*)core_cfg)->memlog=memlog;
  515. LOG(memlog, "Memory status (shm)\n");
  516. shm_status();
  517. ((struct cfg_group_core*)core_cfg)->memlog=old_memlog;
  518. *val = (void*)(long)0;
  519. }
  520. return 0;
  521. }
  522. #endif