/** * Initializes the Peer Manager. * The initial list of peers is taken from the configuration provided * @param config - configuration for initial peers * @returns 1 */ int peer_manager_init(dp_config *config) { int i; peer *p; LM_DBG("peer_manager_init(): Peer Manager initialization...\n"); peer_list = shm_malloc(sizeof(peer_list_t)); peer_list->head = 0; peer_list->tail = 0; peer_list_lock = lock_alloc(); peer_list_lock = lock_init(peer_list_lock); hopbyhop_id = shm_malloc(sizeof(AAAMsgIdentifier)); endtoend_id = shm_malloc(sizeof(AAAMsgIdentifier)); msg_id_lock = lock_alloc(); msg_id_lock = lock_init(msg_id_lock); kam_srand((unsigned int)time(0)); *hopbyhop_id = kam_rand(); *endtoend_id = (time(0)&0xFFF)<<20; *endtoend_id |= kam_rand() & 0xFFFFF; for(i=0;i<config->peers_cnt;i++){ p = new_peer(config->peers[i].fqdn,config->peers[i].realm,config->peers[i].port,config->peers[i].src_addr); if (!p) continue; p->is_dynamic = 0; add_peer(p); } add_timer(1,0,&peer_timer,0); return 1; }
int fork_tcp_process(int child_id, char *desc, int r, int *reader_fd_1) { int pid, child_process_no; int sockfd[2]; int reader_fd[2]; /* for comm. with the tcp children read */ int ret; int i; unsigned int new_seed1; unsigned int new_seed2; /* init */ sockfd[0]=sockfd[1]=-1; reader_fd[0]=reader_fd[1]=-1; ret=-1; if (!is_main){ LM_CRIT("called from a non \"main\" process\n"); goto error; } if (tcp_main_pid){ LM_CRIT("called _after_ starting tcp main\n"); goto error; } if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){ LM_ERR("socketpair failed: %s\n", strerror(errno)); goto error; } if (socketpair(AF_UNIX, SOCK_STREAM, 0, reader_fd)<0){ LM_ERR("socketpair failed: %s\n", strerror(errno)); goto error; } if (tcp_fix_child_sockets(reader_fd)<0){ LM_ERR("failed to set non blocking on child sockets\n"); /* continue, it's not critical (it will go slower under * very high connection rates) */ } lock_get(process_lock); /* set the local process_no */ if (*process_count>=estimated_proc_no) { LM_CRIT("Process limit of %d exceeded. Simulating fork fail\n", estimated_proc_no); lock_release(process_lock); goto error; } child_process_no = *process_count; new_seed1=kam_rand(); new_seed2=random(); pid = fork(); if (pid<0) { lock_release(process_lock); ret=pid; goto end; } if (pid==0){ is_main=0; /* a forked process cannot be the "main" one */ process_no=child_process_no; /* close unneeded unix sockets */ close_extra_socks(child_id, process_no); /* same for unneeded tcp_children <-> tcp_main unix socks */ for (i=0; i<r; i++){ if (tcp_children[i].unix_sock>=0){ close(tcp_children[i].unix_sock); /* tcp_children is per process, so it's safe to change * the unix_sock to -1 */ tcp_children[i].unix_sock=-1; } } daemon_status_on_fork_cleanup(); kam_srand(new_seed1); fastrand_seed(kam_rand()); srandom(new_seed2+time(0)); shm_malloc_on_fork(); #ifdef PROFILING monstartup((u_long) &_start, (u_long) &etext); #endif #ifdef FORK_DONT_WAIT /* record pid twice to avoid the child using it, before - * parent gets a chance to set it*/ pt[process_no].pid=getpid(); #else /* wait for parent to get out of critical zone */ lock_get(process_lock); lock_release(process_lock); #endif close(sockfd[0]); unix_tcp_sock=sockfd[1]; close(reader_fd[0]); if (reader_fd_1) *reader_fd_1=reader_fd[1]; if ((child_id!=PROC_NOCHLDINIT) && (init_child(child_id) < 0)) { LM_ERR("init_child failed for process %d, pid %d, \"%s\"\n", process_no, pt[process_no].pid, pt[process_no].desc); return -1; } return pid; } else { /* parent */ (*process_count)++; #ifdef FORK_DONT_WAIT lock_release(process_lock); #endif /* add the process to the list in shm */ pt[child_process_no].pid=pid; pt[child_process_no].unix_sock=sockfd[0]; pt[child_process_no].idx=r; if (desc){ snprintf(pt[child_process_no].desc, MAX_PT_DESC, "%s child=%d", desc, r); } #ifdef FORK_DONT_WAIT #else lock_release(process_lock); #endif close(sockfd[1]); close(reader_fd[1]); tcp_children[r].pid=pid; tcp_children[r].proc_no=child_process_no; tcp_children[r].busy=0; tcp_children[r].n_reqs=0; tcp_children[r].unix_sock=reader_fd[0]; ret=pid; goto end; } error: if (sockfd[0]!=-1) close(sockfd[0]); if (sockfd[1]!=-1) close(sockfd[1]); if (reader_fd[0]!=-1) close(reader_fd[0]); if (reader_fd[1]!=-1) close(reader_fd[1]); end: return ret; }
/** * Forks a new process. * @param child_id - rank, if equal to PROC_NOCHLDINIT init_child will not be * called for the new forked process (see sr_module.h) * @param desc - text description for the process table * @param make_sock - if to create a unix socket pair for it * @returns the pid of the new process */ int fork_process(int child_id, char *desc, int make_sock) { int pid, child_process_no; int ret; unsigned int new_seed1; unsigned int new_seed2; #ifdef USE_TCP int sockfd[2]; #endif if(unlikely(fork_delay>0)) sleep_us(fork_delay); ret=-1; #ifdef USE_TCP sockfd[0]=sockfd[1]=-1; if(make_sock && !tcp_disable){ if (!is_main){ LM_CRIT("called from a non " "\"main\" process! If forking from a module's " "child_init() fork only if rank==PROC_MAIN or" " give up tcp send support (use 0 for make_sock)\n"); goto error; } if (tcp_main_pid){ LM_CRIT("called, but tcp main is already started\n"); goto error; } if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){ LM_ERR("socketpair failed: %s\n", strerror(errno)); goto error; } } #endif lock_get(process_lock); if (*process_count>=estimated_proc_no) { LM_CRIT("Process limit of %d exceeded. Will simulate fork fail.\n", estimated_proc_no); lock_release(process_lock); goto error; } child_process_no = *process_count; new_seed1=kam_rand(); new_seed2=random(); pid = fork(); if (pid<0) { lock_release(process_lock); ret=pid; goto error; }else if (pid==0){ /* child */ is_main=0; /* a forked process cannot be the "main" one */ process_no=child_process_no; daemon_status_on_fork_cleanup(); /* close tcp unix sockets if this is not tcp main */ #ifdef USE_TCP close_extra_socks(child_id, process_no); #endif /* USE_TCP */ kam_srand(new_seed1); fastrand_seed(kam_rand()); srandom(new_seed2+time(0)); shm_malloc_on_fork(); #ifdef PROFILING monstartup((u_long) &_start, (u_long) &etext); #endif #ifdef FORK_DONT_WAIT /* record pid twice to avoid the child using it, before * parent gets a chance to set it*/ pt[process_no].pid=getpid(); #else /* wait for parent to get out of critical zone. * this is actually relevant as the parent updates * the pt & process_count. */ lock_get(process_lock); lock_release(process_lock); #endif #ifdef USE_TCP if (make_sock && !tcp_disable){ close(sockfd[0]); unix_tcp_sock=sockfd[1]; } #endif if ((child_id!=PROC_NOCHLDINIT) && (init_child(child_id) < 0)) { LM_ERR("init_child failed for process %d, pid %d, \"%s\"\n", process_no, pt[process_no].pid, pt[process_no].desc); return -1; } return pid; } else { /* parent */ (*process_count)++; #ifdef FORK_DONT_WAIT lock_release(process_lock); #endif /* add the process to the list in shm */ pt[child_process_no].pid=pid; if (desc){ strncpy(pt[child_process_no].desc, desc, MAX_PT_DESC-1); } #ifdef USE_TCP if (make_sock && !tcp_disable){ close(sockfd[1]); pt[child_process_no].unix_sock=sockfd[0]; pt[child_process_no].idx=-1; /* this is not a "tcp" process*/ } #endif #ifdef FORK_DONT_WAIT #else lock_release(process_lock); #endif ret=pid; goto end; } error: #ifdef USE_TCP if (sockfd[0]!=-1) close(sockfd[0]); if (sockfd[1]!=-1) close(sockfd[1]); #endif end: return ret; }
/*! \brief * Initialize children */ static int child_init(int rank) { kam_srand((11 + rank) * getpid() * 7); return 0; }