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