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