/* * 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 i; pid_t pid; struct socket_info* si; int* startup_done = NULL; atomic_t *load_p; chd_rank=0; if (dont_fork){ if (udp_listen==0){ LM_ERR("no fork mode requires at least one" " udp listen address, exiting...\n"); goto error; } /* only one address, we ignore all the others */ if (udp_init(udp_listen)==-1) goto error; bind_address=udp_listen; sendipv4=bind_address; sendipv6=bind_address; /*FIXME*/ if (udp_listen->next){ LM_WARN("using only the first listen address (no fork)\n"); } /* 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; } /* main process, receive loop */ set_proc_attrs("stand-alone SIP receiver %.*s", bind_address->sock_str.len, bind_address->sock_str.s ); /* We will call child_init even if we * do not fork - and it will be called with rank 1 because * in fact we behave like a child, not like main process */ if (init_child(1) < 0) { LM_ERR("init_child failed in don't fork\n"); goto error; } if (startup_rlist.a) run_startup_route(); is_main=1; load_p = shm_malloc(sizeof(atomic_t)); if (!load_p) { /* highly improbable */ LM_ERR("no more shm\n"); goto error; } memset(load_p,0,sizeof(atomic_t)); pt[process_no].load = load_p; register_udp_load_stat(&udp_listen->sock_str,load_p); return udp_rcv_loop(); } else { /* don't fork */ for(si=udp_listen;si;si=si->next){ /* create the listening socket (for each address)*/ /* udp */ if (udp_init(si)==-1) goto error; /* get first ipv4/ipv6 socket*/ if ((si->address.af==AF_INET)&& ((sendipv4==0)||(sendipv4->flags&SI_IS_LO))) sendipv4=si; #ifdef USE_IPV6 if((sendipv6==0)&&(si->address.af==AF_INET6)) sendipv6=si; #endif } #ifdef USE_TCP if (!tcp_disable){ for(si=tcp_listen; si; si=si->next){ /* same thing for tcp */ if (tcp_init(si)==-1) goto error; /* get first ipv4/ipv6 socket*/ if ((si->address.af==AF_INET)&& ((sendipv4_tcp==0)||(sendipv4_tcp->flags&SI_IS_LO))) sendipv4_tcp=si; #ifdef USE_IPV6 if((sendipv6_tcp==0)&&(si->address.af==AF_INET6)) sendipv6_tcp=si; #endif } } #ifdef USE_TLS if (!tls_disable){ for(si=tls_listen; si; si=si->next){ /* same as for tcp*/ if (tls_init(si)==-1) goto error; /* get first ipv4/ipv6 socket*/ if ((si->address.af==AF_INET)&& ((sendipv4_tls==0)||(sendipv4_tls->flags&SI_IS_LO))) sendipv4_tls=si; #ifdef USE_IPV6 if((sendipv6_tls==0)&&(si->address.af==AF_INET6)) sendipv6_tls=si; #endif } } #endif /* USE_TLS */ #endif /* USE_TCP */ #ifdef USE_SCTP if (!sctp_disable){ for(si=sctp_listen; si; si=si->next){ /* same thing for sctp */ if (sctp_server_init(si)==-1) goto error; /* get first ipv4/ipv6 socket*/ if ((si->address.af==AF_INET)&& ((sendipv4_sctp==0)||(sendipv4_sctp->flags&SI_IS_LO))) sendipv4_sctp=si; #ifdef USE_IPV6 if((sendipv6_sctp==0)&&(si->address.af==AF_INET6)) sendipv6_sctp=si; #endif } } #endif /* USE_SCTP */ /* 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; } /* udp processes */ for(si=udp_listen; si; si=si->next){ load_p = shm_malloc(sizeof(atomic_t)); if (!load_p) { /* highly improbable */ LM_ERR("no more shm\n"); goto error; } memset(load_p,0,sizeof(atomic_t)); register_udp_load_stat(&si->sock_str,load_p); for(i=0;i<children_no;i++){ chd_rank++; if ( (pid=internal_fork( "UDP receiver"))<0 ) { LM_CRIT("cannot fork UDP process\n"); goto error; } else { if (pid==0) { /* new UDP process */ /* set a more detailed description */ set_proc_attrs("SIP receiver %.*s ", si->sock_str.len, si->sock_str.s); bind_address=si; /* shortcut */ if (init_child(chd_rank) < 0) { LM_ERR("init_child failed for UDP listener\n"); exit(-1); } if(chd_rank == 1 && startup_rlist.a) { if(run_startup_route()< 0) { LM_ERR("Startup route processing failed\n"); exit(-1); } *startup_done = 1; } /* all UDP listeners on same interface * have same SHM load pointer */ pt[process_no].load = load_p; udp_rcv_loop(); exit(-1); } else { /* if the first process that runs startup_route*/ if(chd_rank == 1 && startup_rlist.a) { while(!startup_done) { usleep(5); } shm_free(startup_done); } } } } /*parent*/ /*close(udp_sock)*/; /*if it's closed=>sendto invalid fd errors?*/ } } #ifdef USE_SCTP if(!sctp_disable){ for(si=sctp_listen; si; si=si->next){ for(i=0;i<children_no;i++){ chd_rank++; if ( (pid=internal_fork( "SCTP receiver"))<0 ) { LM_CRIT("cannot fork SCTP process\n"); goto error; } else if (pid==0){ /* new SCTP process */ /* set a more detailed description */ set_proc_attrs("SIP receiver %.*s ", si->sock_str.len, si->sock_str.s); bind_address=si; /* shortcut */ if (init_child(chd_rank) < 0) { LM_ERR("init_child failed\n"); exit(-1); } sctp_server_rcv_loop(); exit(-1); } } } } #endif /* USE_SCTP */ /* this is the main process -> it shouldn't send anything */ bind_address=0; /* fork for the timer process*/ if (start_timer_processes()!=0) { LM_CRIT("cannot start timer process(es)\n"); goto error; } #ifdef USE_TCP if (!tcp_disable){ /* start tcp & tls receivers */ if (tcp_init_children(&chd_rank)<0) goto error; /* start tcp+tls master proc */ 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; /* init modules */ if (init_child(PROC_TCP_MAIN) < 0) { LM_ERR("error in init_child for tcp main\n"); exit(-1); } tcp_main_loop(); exit(-1); } } #endif /* 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"); goto error; } 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 */ return -1; }
void httpd_proc(int rank) { #ifdef LIBMICROHTTPD int status; fd_set rs; fd_set ws; fd_set es; int max; #endif struct httpd_cb *cb = httpd_cb_list; /*child's initial settings*/ if (init_mi_child()!=0) { LM_ERR("failed to init the mi child process\n"); return; } /* Allocating http response buffer */ buffer.s = (char*)pkg_malloc(sizeof(char)*buffer.len); if (buffer.s==NULL) { LM_ERR("oom\n"); return; } while(cb) { if (cb->init_proc_callback) cb->init_proc_callback(); cb = cb->next; } #ifdef LIBMICROHTTPD struct timeval tv; struct sockaddr_in saddr_in; memset(&saddr_in, 0, sizeof(saddr_in)); if (ip.s) saddr_in.sin_addr.s_addr = inet_addr(ip.s); else saddr_in.sin_addr.s_addr = INADDR_ANY; saddr_in.sin_family = AF_INET; saddr_in.sin_port = htons(port); LM_DBG("init_child [%d] - [%d] HTTP Server init [%s:%d]\n", rank, getpid(), (ip.s?ip.s:"INADDR_ANY"), port); set_proc_attrs("HTTPD %s:%d", (ip.s?ip.s:"INADDR_ANY"), port); dmn = MHD_start_daemon(MHD_NO_FLAG|MHD_USE_DEBUG, port, NULL, NULL, &(answer_to_connection), NULL, MHD_OPTION_SOCK_ADDR, &saddr_in, MHD_OPTION_END); if (NULL == dmn) { LM_ERR("unable to start http daemon\n"); return; } while(1) { max = 0; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); if (MHD_YES != MHD_get_fdset (dmn, &rs, &ws, &es, &max)) { LM_ERR("unable to get file descriptors\n"); return; } tv.tv_sec = 1; tv.tv_usec = 0; //LM_DBG("select(%d,%p,%p,%p,%p)\n",max+1, &rs, &ws, &es, &tv); status = select(max+1, &rs, &ws, &es, &tv); if (status < 0) { switch(errno){ case EINTR: LM_DBG("error returned by select:" " [%d] [%d][%s]\n", status, errno, strerror(errno)); break; default: LM_WARN("error returned by select:" " [%d] [%d][%s]\n", status, errno, strerror(errno)); return; } } //LM_DBG("select returned %d\n", status); status = MHD_run(dmn); if (status == MHD_NO) { LM_ERR("unable to run http daemon\n"); return; } } #endif LM_DBG("HTTP Server stopped!\n"); }
/** * 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; }
/*! \brief starts the tcp processes */ int tcp_init_children(int *chd_rank) { int r; //int sockfd[2]; int reader_fd[2]; /* for comm. with the tcp children read */ pid_t pid; struct socket_info *si; atomic_t *load_p; /* 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, si=tcp_listen; si; si=si->next, r++); #ifdef USE_TLS if (! tls_disable) for (si=tls_listen; si; si=si->next, r++); #endif tcp_max_fd_no=counted_processes*2 +r-1 /* timer */ +3; /* stdin/out/err*/ tcp_max_fd_no+=tcp_max_connections; /* create the tcp sock_info structures */ /* copy the sockets --moved to main_loop*/ load_p = shm_malloc(sizeof(atomic_t)); if (!load_p) goto error; memset(load_p,0,sizeof(atomic_t)); register_tcp_load_stat(load_p); /* fork children & create the socket pairs*/ for(r=0; r<tcp_children_no; r++){ /*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; } (*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; bind_address=0; /* force a SEGFAULT if someone uses a non-init. bind address on tcp */ if (init_child(*chd_rank) < 0) { LM_ERR("init_children failed\n"); exit(-1); } tcp_receive_loop(reader_fd[1]); exit(-1); } } return 0; error: return -1; }
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 i,rc; pid_t pid; struct socket_info* si; int* startup_done = NULL; stat_var *load_p = 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"); goto error; } if (udp_listen==0){ LM_ERR("no fork mode requires at least one" " udp listen address, exiting...\n"); goto error; } /* only one address, we ignore all the others */ if (udp_init(udp_listen)==-1) goto error; bind_address=udp_listen; sendipv4=bind_address; sendipv6=bind_address; /*FIXME*/ if (udp_listen->next){ LM_WARN("using only the first listen address (no fork)\n"); } /* 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; } /* main process, receive loop */ set_proc_attrs("stand-alone SIP receiver %.*s", bind_address->sock_str.len, bind_address->sock_str.s ); /* We will call child_init even if we * do not fork - and it will be called with rank 1 because * in fact we behave like a child, not like main process */ if (init_child(1) < 0) { LM_ERR("init_child failed in don't fork\n"); goto error; } if (startup_rlist.a) run_startup_route(); is_main=1; if (register_udp_load_stat(&udp_listen->sock_str, &pt[process_no].load, 1)!=0) { LM_ERR("failed to init udp load statistics\n"); goto error; } clean_write_pipeend(); LM_DBG("waiting for status code from children\n"); rc = wait_for_all_children(); if (rc < 0) { LM_ERR("failed to succesfully init children\n"); return rc; } return udp_rcv_loop(); } else { /* don't fork */ for(si=udp_listen;si;si=si->next){ /* create the listening socket (for each address)*/ /* udp */ if (udp_init(si)==-1) goto error; /* get first ipv4/ipv6 socket*/ if ((si->address.af==AF_INET)&& ((sendipv4==0)||(sendipv4->flags&SI_IS_LO))) sendipv4=si; #ifdef USE_IPV6 if((sendipv6==0)&&(si->address.af==AF_INET6)) sendipv6=si; #endif } #ifdef USE_TCP if (!tcp_disable){ for(si=tcp_listen; si; si=si->next){ /* same thing for tcp */ if (tcp_init(si)==-1) goto error; /* get first ipv4/ipv6 socket*/ if ((si->address.af==AF_INET)& ((sendipv4_tcp==0)||(sendipv4_tcp->flags&SI_IS_LO))) sendipv4_tcp=si; #ifdef USE_IPV6 if((sendipv6_tcp==0)&&(si->address.af==AF_INET6)) sendipv6_tcp=si; #endif } } #ifdef USE_TLS if (!tls_disable){ for(si=tls_listen; si; si=si->next){ /* same as for tcp*/ if (tls_init(si)==-1) goto error; /* get first ipv4/ipv6 socket*/ if ((si->address.af==AF_INET)&& ((sendipv4_tls==0)||(sendipv4_tls->flags&SI_IS_LO))) sendipv4_tls=si; #ifdef USE_IPV6 if((sendipv6_tls==0)&&(si->address.af==AF_INET6)) sendipv6_tls=si; #endif } } #endif /* USE_TLS */ #endif /* USE_TCP */ #ifdef USE_SCTP if (!sctp_disable){ for(si=sctp_listen; si; si=si->next){ /* same thing for sctp */ if (sctp_server_init(si)==-1) goto error; /* get first ipv4/ipv6 socket*/ if ((si->address.af==AF_INET)&& ((sendipv4_sctp==0)||(sendipv4_sctp->flags&SI_IS_LO))) sendipv4_sctp=si; #ifdef USE_IPV6 if((sendipv6_sctp==0)&&(si->address.af==AF_INET6)) sendipv6_sctp=si; #endif } } #endif /* USE_SCTP */ /* 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; } /* udp processes */ for(si=udp_listen; si; si=si->next){ if(register_udp_load_stat(&si->sock_str,&load_p,si->children)!=0){ LM_ERR("failed to init load statistics\n"); goto error; } for(i=0;i<si->children;i++){ chd_rank++; if ( (pid=internal_fork( "UDP receiver"))<0 ) { LM_CRIT("cannot fork UDP process\n"); goto error; } else { if (pid==0) { /* new UDP process */ /* set a more detailed description */ set_proc_attrs("SIP receiver %.*s ", si->sock_str.len, si->sock_str.s); bind_address=si; /* shortcut */ if (init_child(chd_rank) < 0) { LM_ERR("init_child failed for UDP listener\n"); if (send_status_code(-1) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); if (chd_rank == 1 && startup_done) *startup_done = -1; exit(-1); } /* first UDP proc runs statup_route (if defined) */ if(chd_rank == 1 && startup_done!=NULL) { LM_DBG("runing startup for first UDP\n"); if(run_startup_route()< 0) { if (send_status_code(-1) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); *startup_done = -1; LM_ERR("Startup route processing failed\n"); exit(-1); } *startup_done = 1; } if (!no_daemon_mode && send_status_code(0) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); /* all UDP listeners on same interface * have same SHM load pointer */ pt[process_no].load = load_p; udp_rcv_loop(); exit(-1); } else { /* wait for first proc to finish the startup route */ if(chd_rank == 1 && startup_done!=NULL) while( !(*startup_done) ) {usleep(5);handle_sigs();} } } } /*parent*/ /*close(udp_sock)*/; /*if it's closed=>sendto invalid fd errors?*/ } } #ifdef USE_SCTP if(!sctp_disable){ for(si=sctp_listen; si; si=si->next){ for(i=0;i<si->children;i++){ chd_rank++; if ( (pid=internal_fork( "SCTP receiver"))<0 ) { LM_CRIT("cannot fork SCTP process\n"); goto error; } else if (pid==0){ /* new SCTP process */ /* set a more detailed description */ set_proc_attrs("SIP receiver %.*s ", si->sock_str.len, si->sock_str.s); bind_address=si; /* shortcut */ if (init_child(chd_rank) < 0) { LM_ERR("init_child failed\n"); if (send_status_code(-1) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); if( (si==sctp_listen && i==0) && startup_done) *startup_done = -1; exit(-1); } /* was startup route executed so far ? if not, run it only by the * first SCTP proc (first proc from first interface) */ if( (si==sctp_listen && i==0) && startup_done!=NULL && *startup_done==0) { LM_DBG("runing startup for first SCTP\n"); if(run_startup_route()< 0) { LM_ERR("Startup route processing failed\n"); if (send_status_code(-1) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); *startup_done = -1; exit(-1); } *startup_done = 1; } if (!no_daemon_mode && send_status_code(0) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); sctp_server_rcv_loop(); exit(-1); } else { /* wait for first proc to finish the startup route */ if( (si==sctp_listen && i==0) && startup_done!=NULL) while( !(*startup_done) ) {usleep(5);handle_sigs();} } } } } #endif /* USE_SCTP */ /* this is the main process -> it shouldn't send anything */ bind_address=0; /* fork for the timer process*/ if (start_timer_processes()!=0) { LM_CRIT("cannot start timer process(es)\n"); goto error; } #ifdef USE_TCP if (!tcp_disable){ /* start tcp & tls receivers */ if (tcp_init_children(&chd_rank, startup_done)<0) goto error; /* wait for the startup route to be executed */ if( startup_done!=NULL) while( !(*startup_done) ) {usleep(5);handle_sigs();} /* start tcp+tls master proc */ 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; /* init modules */ if (init_child(PROC_TCP_MAIN) < 0) { LM_ERR("error in init_child for tcp main\n"); if (send_status_code(-1) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); exit(-1); } if (!no_daemon_mode && send_status_code(0) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); tcp_main_loop(); exit(-1); } } #endif 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) { if (send_status_code(-1) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); LM_ERR("error in init_child for PROC_MAIN\n"); goto error; } if (!no_daemon_mode && send_status_code(0) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); 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 */ if (!dont_fork && send_status_code(-1) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); return -1; }
static void run_timer_process(struct sr_timer_process *tpl) { unsigned int multiple; unsigned int cnt; struct timeval o_tv; struct timeval tv; utime_t drift; utime_t uinterval; utime_t wait; /* timer re-calibration to compensate drifting */ #define compute_wait_with_drift(_tv,_type) \ do { \ if ( drift > ITIMER_TICK ) { \ wait = (drift >= uinterval) ? 0 : uinterval-drift; \ _tv.tv_sec = wait / 1000000; \ _tv.tv_usec = wait % 1000000; \ drift -= uinterval-wait; \ } else { \ _tv = o_tv; \ } \ }while(0) if ( (tpl->utimer_list==NULL) || ((TIMER_TICK*1000000) == UTIMER_TICK) ) { o_tv.tv_sec = TIMER_TICK; o_tv.tv_usec = 0; multiple = 1; } else { o_tv.tv_sec = UTIMER_TICK / 1000000; o_tv.tv_usec = UTIMER_TICK % 1000000; multiple = (( TIMER_TICK * 1000000 ) / UTIMER_TICK ) / 1000000; } if (tpl->utimer_list && tpl->utimer_list->label) { set_proc_attrs("timer: %s", tpl->utimer_list->label); } else if (tpl->timer_list && tpl->timer_list->label) { set_proc_attrs("timer: %s", tpl->timer_list->label); } LM_DBG("tv = %ld, %ld , m=%d\n", (long)o_tv.tv_sec,(long)o_tv.tv_usec,multiple); drift = 0; uinterval = o_tv.tv_sec * 1000000 + o_tv.tv_usec; if (tpl->utimer_list==NULL) { /* only TIMERs, ticking at TIMER_TICK */ for( ; ; ) { compute_wait_with_drift( tv, 0); select( 0, 0, 0, 0, &tv); timer_ticker( tpl->timer_list, &drift); } } else if (tpl->timer_list==NULL) { /* only UTIMERs, ticking at UTIMER_TICK */ for( ; ; ) { compute_wait_with_drift( tv, 1); select( 0, 0, 0, 0, &tv); utimer_ticker( tpl->utimer_list, &drift); } } else if (multiple==1) { /* TIMERs and UTIMERs, ticking together TIMER_TICK (synced) */ for( ; ; ) { compute_wait_with_drift( tv, 2); select( 0, 0, 0, 0, &tv); timer_ticker( tpl->timer_list, &drift); utimer_ticker( tpl->utimer_list, &drift); } } else { /* TIMERs and UTIMERs, TIMER_TICK is multiple of UTIMER_TICK */ for( cnt=1 ; ; cnt++ ) { compute_wait_with_drift( tv, 3); select( 0, 0, 0, 0, &tv); utimer_ticker(tpl->utimer_list, &drift); if (cnt==multiple) { timer_ticker(tpl->timer_list, &drift); cnt = 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 (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; }