pt.c 14 KB

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