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