/* * called in the OpenSIPS initialization phase by the main process. * forks the binary packet UDP receivers. * * @return: 0 on success */ int start_bin_receivers(void) { pid_t pid; int i; if (udp_init_listener(bin, 0) != 0) return -1; for (i = 1; i <= bin_children; i++) { if ((pid = internal_fork("BIN receiver")) < 0) { LM_CRIT("Cannot fork binary packet receiver process!\n"); return -1; } if (pid == 0) { LM_DBG("CHILD sock: %d\n", bin->socket); child_index = i; set_proc_attrs("BIN receiver %.*s ", bin->sock_str.len, bin->sock_str.s); bind_address = bin; if (init_child(PROC_BIN) < 0) { LM_ERR("init_child failed for BIN listener\n"); report_failure_status(); exit(-1); } bin_receive_loop(); exit(-1); } else LM_DBG("PARENT sock: %d\n", bin->socket); } return 0; }
/** * Main loop, forks the children, bind to addresses, * handle signals. * \return don't return on sucess, -1 on error */ static int main_loop(void) { static int chd_rank; int* startup_done = NULL; chd_rank=0; if (init_debug() != 0) { LM_ERR("failed to init logging levels\n"); goto error; } if (dont_fork) { if (create_status_pipe() < 0) { LM_ERR("failed to create status pipe\n"); goto error; } if (udp_init_nofork() < 0) { LM_ERR("failed to init UDP for no fork mode\n"); goto error; } /* try to drop privileges */ if (do_suid(uid, gid)==-1) goto error; if (start_module_procs()!=0) { LM_ERR("failed to fork module processes\n"); goto error; } /* we need another process to act as the timer*/ if (start_timer_processes()!=0) { LM_CRIT("cannot start timer process(es)\n"); goto error; } is_main=1; udp_start_nofork(); /* udp_start_nofork() returns only if error */ /* in case of failed startup, behave as "attendant" to trigger * proper cleanup sequance (and proper signal handler !!!). * So, reset the dont_fork (as it will force inline signal handling)*/ dont_fork = 0; return -1; } else { /* don't fork */ if (trans_init_all_listeners()<0) { LM_ERR("failed to init all SIP listeners, aborting\n"); goto error; } /* all processes should have access to all the sockets (for sending) * so we open all first*/ if (do_suid(uid, gid)==-1) goto error; /* try to drop privileges */ if (start_module_procs()!=0) { LM_ERR("failed to fork module processes\n"); goto error; } if(startup_rlist.a) {/* if a startup route was defined */ startup_done = (int*)shm_malloc(sizeof(int)); if(startup_done == NULL) { LM_ERR("No more shared memory\n"); goto error; } *startup_done = 0; } if (fix_socket_list(&bin) != 0) { LM_ERR("failed to initialize binary interface socket list!\n"); goto error; } /* OpenSIPS <--> OpenSIPS communication interface */ if (bin && start_bin_receivers() != 0) { LM_CRIT("cannot start binary interface receiver processes!\n"); goto error; } /* fork for the timer process*/ if (start_timer_processes()!=0) { LM_CRIT("cannot start timer process(es)\n"); goto error; } /* fork all processes required by UDP network layer */ if (udp_start_processes( &chd_rank, startup_done)<0) { LM_CRIT("cannot start TCP processes\n"); goto error; } /* fork all processes required by TCP network layer */ if (tcp_start_processes( &chd_rank, startup_done)<0) { LM_CRIT("cannot start TCP processes\n"); goto error; } } /* this is the main process -> it shouldn't send anything */ bind_address=0; if (startup_done) { if (*startup_done==0) LM_CRIT("BUG: startup route defined, but not run :( \n"); shm_free(startup_done); } /* main process left */ is_main=1; set_proc_attrs("attendant"); if (init_child(PROC_MAIN) < 0) { LM_ERR("error in init_child for PROC_MAIN\n"); report_failure_status(); goto error; } report_conditional_status( (!no_daemon_mode), 0); for(;;) { handle_sigs(); pause(); } /*return 0; */ error: is_main=1; /* if we are here, we are the "main process", any forked children should exit with exit(-1) and not ever use return */ report_conditional_status( (!dont_fork), -1); return -1; }
int start_module_procs(void) { struct sr_module *m; unsigned int n; unsigned int l; int x; for( m=modules ; m ; m=m->next) { if (m->exports->procs==NULL) continue; for( n=0 ; m->exports->procs[n].name ; n++) { if ( !m->exports->procs[n].no || !m->exports->procs[n].function ) continue; /* run pre-fork function */ if (m->exports->procs[n].pre_fork_function) if (m->exports->procs[n].pre_fork_function()!=0) { LM_ERR("pre-fork function failed for process \"%s\" " "in module %s\n", m->exports->procs[n].name, m->exports->name); return -1; } /* fork the processes */ for ( l=0; l<m->exports->procs[n].no ; l++) { LM_DBG("forking process \"%s\"/%d for module %s\n", m->exports->procs[n].name, l, m->exports->name); x = internal_fork( m->exports->procs[n].name, ((m->exports->procs[n].flags&PROC_FLAG_HAS_IPC) ? 0 : OSS_PROC_NO_IPC)|OSS_PROC_IS_EXTRA, TYPE_MODULE ); if (x<0) { LM_ERR("failed to fork process \"%s\"/%d for module %s\n", m->exports->procs[n].name, l, m->exports->name); return -1; } else if (x==0) { /* new process */ /* initialize the process for the rest of the modules */ if ( m->exports->procs[n].flags&PROC_FLAG_INITCHILD ) { if (init_child(PROC_MODULE) < 0) { LM_ERR("error in init_child for PROC_MODULE\n"); report_failure_status(); exit(-1); } report_conditional_status( (!no_daemon_mode), 0); } else clean_write_pipeend(); /* run the function */ m->exports->procs[n].function(l); /* we shouldn't get here */ exit(0); } } /* run post-fork function */ if (m->exports->procs[n].post_fork_function) if (m->exports->procs[n].post_fork_function()!=0) { LM_ERR("post-fork function failed for process \"%s\" " "in module %s\n", m->exports->procs[n].name, m->exports->name); return -1; } } } return 0; }
int tcp_start_processes(int *chd_rank, int *startup_done) { int r, n; int reader_fd[2]; /* for comm. with the tcp children read */ pid_t pid; struct socket_info *si; stat_var *load_p = NULL; if (tcp_disabled) return 0; /* estimate max fd. no: * 1 tcp send unix socket/all_proc, * + 1 udp sock/udp proc + 1 tcp_child sock/tcp child* * + no_listen_tcp */ for( r=0,n=PROTO_FIRST ; n<PROTO_LAST ; n++ ) if ( is_tcp_based_proto(n) ) for(si=protos[n].listeners; si ; si=si->next,r++ ); if (register_tcp_load_stat( &load_p )!=0) { LM_ERR("failed to init tcp load statistic\n"); goto error; } /* start the TCP workers & create the socket pairs */ for(r=0; r<tcp_children_no; r++){ /* create sock to communicate from TCP main to worker */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, reader_fd)<0){ LM_ERR("socketpair failed: %s\n", strerror(errno)); goto error; } (*chd_rank)++; pid=internal_fork("SIP receiver TCP"); if (pid<0){ LM_ERR("fork failed\n"); goto error; }else if (pid>0){ /* parent */ close(reader_fd[1]); tcp_children[r].pid=pid; tcp_children[r].proc_no=process_no; tcp_children[r].busy=0; tcp_children[r].n_reqs=0; tcp_children[r].unix_sock=reader_fd[0]; }else{ /* child */ set_proc_attrs("TCP receiver"); pt[process_no].idx=r; pt[process_no].load = load_p; if (init_child(*chd_rank) < 0) { LM_ERR("init_children failed\n"); report_failure_status(); if (startup_done) *startup_done = -1; exit(-1); } /* was startup route executed so far ? */ if (startup_done!=NULL && *startup_done==0 && r==0) { LM_DBG("runing startup for first TCP\n"); if(run_startup_route()< 0) { LM_ERR("Startup route processing failed\n"); report_failure_status(); *startup_done = -1; exit(-1); } *startup_done = 1; } report_conditional_status( 1, 0); tcp_worker_proc( reader_fd[1] ); exit(-1); } } /* wait for the startup route to be executed */ if (startup_done) while (!(*startup_done)) { usleep(5); handle_sigs(); } /* start the TCP manager process */ if ( (pid=internal_fork( "TCP main"))<0 ) { LM_CRIT("cannot fork tcp main process\n"); goto error; }else if (pid==0){ /* child */ /* close the TCP inter-process sockets */ close(unix_tcp_sock); unix_tcp_sock = -1; close(pt[process_no].unix_sock); pt[process_no].unix_sock = -1; report_conditional_status( (!no_daemon_mode), 0); tcp_main_server(); exit(-1); } return 0; error: return -1; }
/** * Main loop, forks the children, bind to addresses, * handle signals. * \return don't return on sucess, -1 on error */ static int main_loop(void) { static int chd_rank; int* startup_done = NULL; chd_rank=0; if (start_module_procs()!=0) { LM_ERR("failed to fork module processes\n"); goto error; } if(startup_rlist.a) {/* if a startup route was defined */ startup_done = (int*)shm_malloc(sizeof(int)); if(startup_done == NULL) { LM_ERR("No more shared memory\n"); goto error; } *startup_done = 0; } /* fork for the timer process*/ if (start_timer_processes()!=0) { LM_CRIT("cannot start timer process(es)\n"); goto error; } /* fork all processes required by UDP network layer */ if (udp_start_processes( &chd_rank, startup_done)<0) { LM_CRIT("cannot start TCP processes\n"); goto error; } /* fork all processes required by TCP network layer */ if (tcp_start_processes( &chd_rank, startup_done)<0) { LM_CRIT("cannot start TCP processes\n"); goto error; } /* this is the main process -> it shouldn't send anything */ bind_address=0; if (startup_done) { if (*startup_done==0) LM_CRIT("BUG: startup route defined, but not run :( \n"); shm_free(startup_done); } /* main process left */ is_main=1; set_proc_attrs("attendant"); if (init_child(PROC_MAIN) < 0) { LM_ERR("error in init_child for PROC_MAIN\n"); report_failure_status(); goto error; } report_conditional_status( (!no_daemon_mode), 0); for(;;){ handle_sigs(); pause(); } /*return 0; */ error: is_main=1; /* if we are here, we are the "main process", any forked children should exit with exit(-1) and not ever use return */ report_failure_status(); return -1; }