static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, struct dm_btree_value_type *vt, unsigned left_index) { int r; struct btree_node *parent; struct child left, right; parent = dm_block_data(shadow_current(s)); r = init_child(info, vt, parent, left_index, &left); if (r) return r; r = init_child(info, vt, parent, left_index + 1, &right); if (r) { exit_child(info, &left); return r; } __rebalance2(info, parent, &left, &right); r = exit_child(info, &left); if (r) { exit_child(info, &right); return r; } return exit_child(info, &right); }
static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info, struct dm_btree_value_type *vt, unsigned left_index) { int r; struct btree_node *parent = dm_block_data(shadow_current(s)); struct child left, center, right; /* * FIXME: fill out an array? */ r = init_child(info, vt, parent, left_index, &left); if (r) return r; r = init_child(info, vt, parent, left_index + 1, ¢er); if (r) { exit_child(info, &left); return r; } r = init_child(info, vt, parent, left_index + 2, &right); if (r) { exit_child(info, &left); exit_child(info, ¢er); return r; } __rebalance3(info, parent, &left, ¢er, &right); r = exit_child(info, &left); if (r) { exit_child(info, ¢er); exit_child(info, &right); return r; } r = exit_child(info, ¢er); if (r) { exit_child(info, &right); return r; } r = exit_child(info, &right); if (r) return r; return 0; }
/* starts the tcp processes */ int tcp_init_children() { int r; int sockfd[2]; int reader_fd[2]; /* for comm. with the tcp children read */ pid_t pid; /* create the tcp sock_info structures */ /* copy the sockets --moved to main_loop*/ /* fork children & create the socket pairs*/ for(r=0; r<tcp_children_no; r++){ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){ LOG(L_ERR, "ERROR: tcp_main: socketpair failed: %s\n", strerror(errno)); goto error; } if (socketpair(AF_UNIX, SOCK_STREAM, 0, reader_fd)<0){ LOG(L_ERR, "ERROR: tcp_main: socketpair failed: %s\n", strerror(errno)); goto error; } process_no++; pid=fork(); if (pid<0){ LOG(L_ERR, "ERROR: tcp_main: fork failed: %s\n", strerror(errno)); goto error; }else if (pid>0){ /* parent */ close(sockfd[1]); 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]; pt[process_no].pid=pid; pt[process_no].unix_sock=sockfd[0]; pt[process_no].idx=r; strncpy(pt[process_no].desc, "tcp receiver", MAX_PT_DESC); }else{ /* child */ close(sockfd[0]); unix_tcp_sock=sockfd[1]; bind_address=0; /* force a SEGFAULT if someone uses a non-init. bind address on tcp */ if (init_child(r+children_no+1) < 0) { LOG(L_ERR, "init_children failed\n"); goto error; } tcp_receive_loop(reader_fd[1]); } } return 0; error: return -1; }
/* * Control ops entry point: * * Requests handled completely: * DDI_CTLOPS_INITCHILD * DDI_CTLOPS_UNINITCHILD * All others are passed to the parent. */ static int acpinex_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg, void *result) { int rval = DDI_SUCCESS; switch (op) { case DDI_CTLOPS_INITCHILD: rval = init_child((dev_info_t *)arg); break; case DDI_CTLOPS_UNINITCHILD: impl_ddi_sunbus_removechild((dev_info_t *)arg); break; case DDI_CTLOPS_REPORTDEV: { if (rdip == (dev_info_t *)0) return (DDI_FAILURE); cmn_err(CE_CONT, "?acpinex: %s@%s, %s%d\n", ddi_node_name(rdip), ddi_get_name_addr(rdip), ddi_driver_name(rdip), ddi_get_instance(rdip)); break; } default: rval = ddi_ctlops(dip, rdip, op, arg, result); break; } return (rval); }
/* Generate children*/ static void fork_children(void) { while (shm->running_childs < max_children) { int childno; int pid = 0; if (shm->spawn_no_more == TRUE) return; /* a new child means a new seed, or the new child * will do the same syscalls as the one in the child it's replacing. * (special case startup, or we reseed unnecessarily) */ if (shm->ready == TRUE) reseed(); /* Find a space for it in the pid map */ childno = find_childno(EMPTY_PIDSLOT); if (childno == CHILD_NOT_FOUND) { outputerr("## Pid map was full!\n"); dump_childnos(); exit_main_fail(); } fflush(stdout); pid = fork(); if (pid == 0) { /* Child process. */ init_child(childno); child_process(); debugf("child %d %d exiting.\n", childno, getpid()); close_logfile(&this_child->logfile); _exit(EXIT_SUCCESS); } else { if (pid == -1) { /* We failed, wait for a child to exit before retrying. */ if (shm->running_childs > 0) return; output(0, "couldn't create child! (%s)\n", strerror(errno)); panic(EXIT_FORK_FAILURE); exit_main_fail(); } } shm->children[childno]->pid = pid; shm->running_childs++; debugf("Created child %d (pid:%d) [total:%d/%d]\n", childno, pid, shm->running_childs, max_children); if (shm->exit_reason != STILL_RUNNING) return; } shm->ready = TRUE; debugf("created enough children\n"); }
void quadtree_insert(void* element, QuadTreeNode* node){ //... Try to insert particle i at node n in quadtree // ... By construction, each leaf will contain either // ... 1 or 0 particles struct point_t middle_point = {0, 0}; //printf("middle_point: %d\n", middle_point.x); //printf("middle_point: %d\n", middle_point.y); if(quadtree_is_leaf(node)){ if(node->data != NULL){ //just_one particle //add n's four children to the Quadtree node->children = (QuadTreeNode **)malloc(NUM_CHILDREN * sizeof(QuadTreeNode*)); //printf("quadtree_insert: %d\n", ((struct cell_t*)(node->data))->x); //printf("quadtree_insert: %d\n", ((struct cell_t*)(node->data))->y); int i; for(i=0; i < NUM_CHILDREN; i++){ QuadTreeNode* child = init_child(node, i); node->children[i] = child; } //move the particle already in n into the child //in which it lies // struct point_t middle_point = get_middle_point(node->rect); middle_point = get_middle_point(*node->rect); int p = get_position_forward(node, middle_point); //printf("quadtree_insert: %d\n", ((struct cell_t*)(node->data))->x); //printf("quadtree_insert: %d\n", ((struct cell_t*)(node->data))->y); printf("quadtree_insert over leaf node (%d, %d). Recursive call...\n", ((struct cell_t*)(node->data))->x, ((struct cell_t*)(node->data))->y); node->children[p]->data = node->data; node->data = NULL; //let c be child in which particle i lies //QuadInsert(i,c) int q = get_position(element, middle_point); quadtree_insert(element, node->children[q]); }else{ //... n is a leaf //store particle i in node n node->data = element; printf("quadtree_insert over empty leaf. Element (%d, %d) finding its place.\n", ((struct cell_t*)(node->data))->x, ((struct cell_t*)(node->data))->y); //printf("quadtree_insert:ya %d\n", ((struct cell_t*)(node->data))->x); //printf("quadtree_insert:ya %d\n", ((struct cell_t*)(node->data))->y); } }else{ //more than one nodes in the subtree //determine which child c of node n particle i lies in //QuadInsert(i,c) middle_point = get_middle_point(*node->rect); int q = get_position(element, middle_point); quadtree_insert(element, node->children[q]); } }
int main(int argc, char *argv[], char **envp) { struct cmd_syndesc *ts; afs_int32 code; #ifdef AFS_AIX32_ENV /* * The following signal action for AIX is necessary so that in case of a * crash (i.e. core is generated) we can include the user's data section * in the core dump. Unfortunately, by default, only a partial core is * generated which, in many cases, isn't too useful. */ struct sigaction nsa; sigemptyset(&nsa.sa_mask); nsa.sa_handler = SIG_DFL; nsa.sa_flags = SA_FULLDUMP; sigaction(SIGSEGV, &nsa, NULL); #endif zero_argc = argc; zero_argv = argv; init_child(*argv); ts = cmd_CreateSyntax(NULL, CommandProc, 0, "change user's password"); #define aXFLAG 0 #define aPRINCIPAL 1 #define aPASSWORD 2 #define aNEWPASSWORD 3 #define aCELL 4 #define aSERVERS 5 #define aPIPE 6 cmd_AddParm(ts, "-x", CMD_FLAG, CMD_OPTIONAL, "(obsolete, noop)"); cmd_AddParm(ts, "-principal", CMD_SINGLE, CMD_OPTIONAL, "user name"); cmd_AddParm(ts, "-password", CMD_SINGLE, CMD_OPTIONAL, "user's password"); cmd_AddParm(ts, "-newpassword", CMD_SINGLE, CMD_OPTIONAL, "user's new password"); cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name"); cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL, "explicit list of servers"); cmd_AddParm(ts, "-pipe", CMD_FLAG, CMD_OPTIONAL, "silent operation"); code = cmd_Dispatch(argc, argv); exit(code != 0); }
t_process *add_child(t_process *father) { t_process *tmp; t_process *child; child = create_list(); init_child(father, child); if (father->child == NULL) father->child = child; else { tmp = father->child; while (tmp->next != NULL) tmp = tmp->next; tmp->next = child; } return (child); }
void ForkWrapper::start() { // Create the process & socket pair. int sockets[2]; socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); parent_fd = sockets[0]; child_fd = sockets[1]; pid = fork(); // Child process if(!pid) { //printf("ForkWrapper::start %d %d\n", __LINE__, getpid()); BC_Signals::reset_locks(); BC_Signals::set_sighup_exit(1); init_child(); run(); _exit(0); } }
/* * 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; }
void timeout_listener_process(int rank) { struct sockaddr_un saddr_un; struct sockaddr_un *s_un; struct sockaddr_in saddr_in; struct sockaddr_in *s_in; struct sockaddr_in6 *s_in6; int connect_fd; char buffer[BUF_LEN]; str dlg_id; char* p; unsigned int h_entry, h_id; str id; char* socket_name; unsigned short port; struct sockaddr* saddr; int len, i,n; int optval = 1; struct sockaddr rtpp_info; struct rtpp_notify_node *rtpp_lst; if (init_child(PROC_MODULE) != 0) { LM_ERR("cannot init child process"); return; } if (strncmp("tcp:", rtpp_notify_socket.s, 4) == 0) { rtpp_notify_socket.s += 4; rtpp_notify_socket.len -= 4; p = strrchr(rtpp_notify_socket.s, ':'); if (!p) { LM_ERR("invalid udp address <%.*s>\n", rtpp_notify_socket.len, rtpp_notify_socket.s); return; } n = p- rtpp_notify_socket.s; socket_name = (char *)pkg_malloc(n +1); if(!socket_name) { LM_ERR("no more private memory\n"); return; } memcpy(socket_name, rtpp_notify_socket.s, n); socket_name[n] = '\0'; id.s = p+1; id.len = rtpp_notify_socket.len - n -1; port= str2s(id.s, id.len, &n); if(n) { LM_ERR("Bad format for socket name. Expected ip:port\n"); return; } memset(&saddr_in, 0, sizeof(saddr_in)); saddr_in.sin_addr.s_addr = inet_addr(socket_name); saddr_in.sin_family = AF_INET; saddr_in.sin_port = htons(port); socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd == -1) { LM_ERR("can't create timeout socket\n"); return; } saddr = (struct sockaddr*)&saddr_in; len = sizeof(saddr_in); LM_DBG("binding socket %d to %s:%d\n", socket_fd, socket_name, port); } else { if(strncmp("unix:", rtpp_notify_socket.s, 5) == 0) { rtpp_notify_socket.s += 5; rtpp_notify_socket.len -= 5; } /* create socket */ socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (socket_fd == -1) { LM_ERR("Failed to create unix socket\n"); return; } memset(&saddr_un, 0, sizeof(struct sockaddr_un)); saddr_un.sun_family = AF_LOCAL; strncpy(saddr_un.sun_path, rtpp_notify_socket.s, sizeof(saddr_un.sun_path) - 1); saddr = (struct sockaddr*)&saddr_un; len = sizeof(saddr_un); LM_DBG("binding unix socket %s\n", rtpp_notify_socket.s); } if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(optval)) == -1) { LM_ERR("setsockopt failed %s\n", strerror(errno)); return; } if (bind(socket_fd, saddr, len) == -1) { LM_ERR("failed to bind to socket: %s\n", strerror(errno)); return; } /* open socket for listening */ if(listen(socket_fd, 10) == -1) { LM_ERR("socket listen failed\n"); close(socket_fd); return; } pfds = (struct pollfd *)pkg_malloc(pfds_size*sizeof(struct pollfd)); if (!pfds) { LM_ERR("no more pkg memory\n"); return; } pfds[0].fd = socket_fd; pfds[nfds++].events = POLLIN; for(;;) { nr_events = poll(pfds, nfds, -1); if (nr_events < 0) continue; /* check if the rtpproxy list needs updates */ lock_get(rtpp_notify_h->lock); if (rtpp_notify_h->changed) { /* update list */ update_rtpproxy_list(); rtpp_notify_h->changed = 0; } lock_release(rtpp_notify_h->lock); /* there is a new connection */ if (pfds[0].revents & POLLIN) { i = sizeof(rtpp_info); memset(&rtpp_info, 0, i); connect_fd = accept(socket_fd, &rtpp_info, (socklen_t *)&i); if(connect_fd < 0) { LM_ERR("socket accept failed\n"); continue; } /* if it is a unix socket, try to authenticate it */ if (rtpp_info.sa_family == AF_UNIX) { s_un = (struct sockaddr_un*)&rtpp_info; /* check if the socket is already opened */ lock_get(rtpp_notify_h->lock); for (rtpp_lst = rtpp_notify_h->rtpp_list; rtpp_lst; rtpp_lst = rtpp_lst->next) if ( rtpp_lst->mode == 0 && !strcmp(rtpp_lst->addr, s_un->sun_path)) break; /* if not found add a new one */ if (!rtpp_lst) { /* leave the lock for a moment */ lock_release(rtpp_notify_h->lock); rtpp_lst = (struct rtpp_notify_node*) shm_malloc(sizeof(struct rtpp_notify_node)); if (!rtpp_lst) { LM_ERR("no shm more memory\n"); return; } rtpp_lst->index = 0; rtpp_lst->mode = 0; rtpp_lst->addr = 0; /* copy the socket name */ len = strlen(s_un->sun_path); rtpp_lst->addr = (char *)shm_malloc(len + 1); if (!rtpp_lst->addr) { LM_ERR("no more shm memory\n"); return; } memcpy(rtpp_lst->addr, s_un->sun_path, len + 1); lock_get(rtpp_notify_h->lock); rtpp_lst->next = rtpp_notify_h->rtpp_list; if (!rtpp_notify_h->rtpp_list) rtpp_notify_h->rtpp_list = rtpp_lst; } } else { /* search if I can find this connection */ if (rtpp_info.sa_family == AF_INET) { s_in = (struct sockaddr_in*)&rtpp_info; lock_get(rtpp_notify_h->lock); for (rtpp_lst = rtpp_notify_h->rtpp_list; rtpp_lst; rtpp_lst = rtpp_lst->next) if (rtpp_lst->mode == 1 && memcmp(rtpp_lst->addr, &s_in->sin_addr.s_addr, 4) == 0) break; } else if (rtpp_info.sa_family == AF_INET6) { s_in6 = (struct sockaddr_in6*)&rtpp_info; lock_get(rtpp_notify_h->lock); for (rtpp_lst = rtpp_notify_h->rtpp_list; rtpp_lst; rtpp_lst = rtpp_lst->next) if (rtpp_lst->mode == 6 && memcmp(rtpp_lst->addr, s_in6->sin6_addr.s6_addr, 16) == 0) break; } else { LM_ERR("cannot accept this type of connection\n"); continue; } } if (!rtpp_lst) { lock_release(rtpp_notify_h->lock); LM_DBG("unknown rtpproxy -- ignoring\n"); shutdown(connect_fd, SHUT_RDWR); close(connect_fd); } else { /* valid connection - checking if already connected */ if (rtpp_lst->index) { LM_DBG("rtpproxy restarted - update connection status\n"); shutdown(rtpp_lst->fd, SHUT_RDWR); close(rtpp_lst->fd); } else { rtpp_lst->index = nfds++; if (nfds > pfds_size) { pfds_size *= 2; pfds = (struct pollfd*)pkg_realloc(pfds, pfds_size*sizeof(struct pollfd)); } } LM_DBG("rtpproxy accepted\n"); pfds[rtpp_lst->index].fd = connect_fd; pfds[rtpp_lst->index].events = POLLIN; rtpp_lst->fd = connect_fd; lock_release(rtpp_notify_h->lock); } nr_events--; } for (i=1; (nr_events && i<nfds); i++) { if (!(pfds[i].revents & POLLIN)) continue; nr_events--; do len = read(pfds[i].fd, buffer, BUF_LEN); while (len == -1 && errno == EINTR); if (len < 0) { LM_ERR("reading from socket failed: %s\n",strerror(errno)); continue; } if (!len) { LM_DBG("closing rtpproxy\n"); lock_get(rtpp_notify_h->lock); for (rtpp_lst=rtpp_notify_h->rtpp_list; rtpp_lst;rtpp_lst=rtpp_lst->next) if (rtpp_lst->index == i) break; if (!rtpp_lst) { LM_ERR("BUG - rtpproxy not found\n"); lock_release(rtpp_notify_h->lock); continue; } rtpp_lst->index = 0; lock_release(rtpp_notify_h->lock); nfds--; shutdown(i, SHUT_RDWR); close(i); if (nfds == i) continue; pfds[i].fd = pfds[nfds].fd; lock_get(rtpp_notify_h->lock); for (rtpp_lst=rtpp_notify_h->rtpp_list; rtpp_lst; rtpp_lst=rtpp_lst->next) if (rtpp_lst->index == nfds) break; if (!rtpp_lst) { LM_ERR("BUG - rtpproxy index mismatch\n"); lock_release(rtpp_notify_h->lock); continue; } rtpp_lst->index = i; lock_release(rtpp_notify_h->lock); continue; } dlg_id.s = buffer; dlg_id.len = len; /*strlen(buffer);*/ trim(&dlg_id); LM_DBG("Timeout detected on call [%.*s]\n", len, buffer); /* the message is: h_entry.h_id */ p = memchr(dlg_id.s, '.', dlg_id.len); if(p == NULL) { LM_ERR("Wrong formated message received from rtpproxy [%.*s]\n", len, buffer); continue; } id.s = dlg_id.s; id.len = p-dlg_id.s; if(str2int(&id, &h_entry)< 0) { LM_ERR("Wrong formated message received from rtpproxy [%.*s]\n", len, buffer); continue; } id.s = p+ 1; id.len = dlg_id.len - id.len - 1; if(str2int(&id, &h_id)< 0) { LM_ERR("Wrong formated message received from rtpproxy [%.*s]\n", len, buffer); continue; } LM_DBG("hentry = %u, h_id = %u\n", h_entry, h_id); if(dlg_api.terminate_dlg(h_entry, h_id)< 0) LM_ERR("Failed to terminate dialog h_entry=[%u], h_id=[%u]\n", h_entry, h_id); } } }
/* Generate children*/ static void fork_children(void) { while (shm->running_childs < max_children) { int pidslot; int pid = 0; if (shm->spawn_no_more == TRUE) return; /* a new child means a new seed, or the new child * will do the same syscalls as the one in the pidslot it's replacing. * (special case startup, or we reseed unnecessarily) */ if (shm->ready == TRUE) reseed(); /* Find a space for it in the pid map */ pidslot = find_pid_slot(EMPTY_PIDSLOT); if (pidslot == PIDSLOT_NOT_FOUND) { outputerr("## Pid map was full!\n"); dump_pid_slots(); exit(EXIT_FAILURE); } if (logging == TRUE) { int fd; fd = fileno(shm->logfiles[pidslot]); if (ftruncate(fd, 0) == 0) lseek(fd, 0, SEEK_SET); } (void)alarm(0); fflush(stdout); pid = fork(); if (pid == 0) { /* Child process. */ init_child(pidslot); child_process(pidslot); debugf("child %d exiting.\n", pidslot); _exit(EXIT_SUCCESS); } else { if (pid == -1) { output(0, "couldn't create child! (%s)\n", strerror(errno)); shm->exit_reason = EXIT_FORK_FAILURE; exit(EXIT_FAILURE); } } shm->pids[pidslot] = pid; shm->running_childs++; debugf("Created child %d in pidslot %d [total:%d/%d]\n", shm->pids[pidslot], pidslot, shm->running_childs, max_children); if (shm->exit_reason != STILL_RUNNING) return; } shm->ready = TRUE; debugf("created enough children\n"); }
/*! \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; }
/* * Spawn listeners */ int init_unixsock_children(void) { int i; pid_t pid; #ifdef USE_TCP int sockfd[2]; #endif if (!unixsock_name || *unixsock_name == '\0') { return 1; } if (get_uptime() < 0) { return -1; } if (register_core_commands() < 0) { close(rx_sock); close(tx_sock); return -1; } for(i = 0; i < unixsock_children; i++) { process_no++; #ifdef USE_TCP if(!tcp_disable){ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){ LOG(L_ERR, "ERROR: init_unixsock_server: socketpair" " failed: %s\n", strerror(errno)); return -1; } } #endif pid = fork(); if (pid < 0) { LOG(L_ERR, "init_unixsock_server: Unable to fork: %s\n", strerror(errno)); close(rx_sock); close(tx_sock); return -1; } else if (pid == 0) { /* child */ #ifdef USE_TCP if (!tcp_disable){ close(sockfd[0]); unix_tcp_sock=sockfd[1]; } #endif if (init_child(PROC_UNIXSOCK) < 0) { LOG(L_ERR, "init_unixsock_server: Error in " "init_child\n"); close(rx_sock); close(tx_sock); return -1; } unix_server_loop(); /* Never returns */ } /* Parent */ pt[process_no].pid = pid; strncpy(pt[process_no].desc, "unix domain socket server", MAX_PT_DESC); #ifdef USE_TCP if (!tcp_disable){ close(sockfd[1]); pt[process_no].unix_sock=sockfd[0]; pt[process_no].idx=-1; /* this is not a "tcp" process*/ } #endif } DBG("init_unixsock_server: Unix domain socket server successfully initialized @ %s\n", unixsock_name); return 1; }
/*----------------------------------------------------------------------------- main -----------------------------------------------------------------------------*/ int main(int argc, char** argv) { if (argc < 2) { fprintf(stderr, "Syntax: %s <tracee> [<tracee args>]\n", argv[0]); return -1; } main_child = fork(); if (main_child == 0) { int argv_len = 0; for (int i = 1; i < argc; ++i) if (argv[i]) argv_len += strlen(argv[i]) + 1; char* new_argv = new char[argv_len + 1]; for (int i = 1; i < argc; ++i) { if (i > 1) strcat(new_argv, " "); strcat(new_argv, argv[i]); } char* execve_args[] = {(char*)"sh", (char*)"-c", new_argv, NULL}; ptrace(PTRACE_TRACEME, 0, 0, 0); execv("/bin/sh", execve_args); } else { unsigned char first_fork = 1; int status; pid_t pid; std::map<pid_t, struct minimal_childstate*>::iterator it; struct minimal_childstate* child = init_child(main_child); childs.insert(std::pair<pid_t, struct minimal_childstate*>(main_child, child)); // wait for the main child first to set the ptrace options if ((waitpid(-1, &status, 0) == main_child) && WIFSTOPPED(status)) { child_set_options(child); ptrace(PTRACE_SYSCALL, main_child, NULL, 0); } else { fprintf(stderr, "ERROR: Main child initialization failed\n"); force_shutdown(); } while ((pid = waitpid(-1, &status, __WALL | WUNTRACED)) != -1) { it = childs.find(pid); if (it == childs.end()) { if (childs.find(pid) == childs.end()) childs.insert(std::pair<pid_t, struct minimal_childstate*>(pid, init_child(pid))); } else { child = it->second; } if (WIFEXITED(status)) { child->child_exited = 1; check_shutdown(); ptrace(PTRACE_SYSCALL, pid, NULL, 0); } else if (WIFSTOPPED(status)) { if (WSTOPSIG(status) == (SIGTRAP|0x80)) { if (!child->child_in_syscall) { long syscall_no = ptrace(PTRACE_PEEKUSER, pid, 8 * ORIG_RAX, NULL); if (is_whitelisted_syscall(syscall_no)) child->child_syscalls_whitelisted++; child->child_syscalls++; } child->child_in_syscall = !child->child_in_syscall; ptrace(PTRACE_SYSCALL, pid, NULL, 0); } else if (WSTOPSIG(status) == SIGTRAP) { int event = ((status & 0x000F0000) >> 16); if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK || event == PTRACE_EVENT_CLONE) { long newpid; ptrace(PTRACE_GETEVENTMSG, pid, 0, &newpid); if (childs.find(newpid) == childs.end()) childs.insert(std::pair<pid_t, struct minimal_childstate*>(newpid, init_child(newpid))); //printf("fork event from child: %d [== FORK ==>] %d\n", pid, (pid_t)newpid); if (first_fork) { first_fork = 0; gettimeofday(&start_time, NULL); } } else { //fprintf(stderr, "ERROR: Unexpected SIGTRAP from child %d - event: %d\n", pid, event); //force_shutdown(); } ptrace(PTRACE_SYSCALL, pid, NULL, 0); } else if (WSTOPSIG(status) == SIGSTOP) { if (!child->child_resumed) child->child_resumed = 1; else child->child_signals++; ptrace(PTRACE_SYSCALL, pid, NULL, 0); } else { child->child_signals++; ptrace(PTRACE_SYSCALL, pid, NULL, (void*)WSTOPSIG(status)); } } else {
int start_timer_processes(void) { struct sr_timer_process *tpl; pid_t pid; /* * A change of the way timers were run. In the pre-1.5 times, * all timer processes had their own jiffies and just the first * one was doing the global ones. Now, there's a separate process * that increases jiffies - run_timer_process_jif(), and the rest * just use that one. * * The main reason for this change was when a function that relied * on jiffies for its timeouts got called from the timer thread and * was unable to detect timeouts. */ if ( (pid=internal_fork("time_keeper"))<0 ) { LM_CRIT("cannot fork time keeper process\n"); goto error; } else if (pid==0) { /* new process */ clean_write_pipeend(); run_timer_process_jif(); exit(-1); } for( tpl=timer_proc_list ; tpl ; tpl=tpl->next ) { if (tpl->timer_list==NULL && tpl->utimer_list==NULL) continue; /* fork a new process */ if ( (pid=internal_fork("timer"))<0 ) { LM_CRIT("cannot fork timer process\n"); goto error; } else if (pid==0) { /* new process */ /* run init if required */ if ( tpl->flags&TIMER_PROC_INIT_FLAG ) { LM_DBG("initializing timer\n"); inc_init_timer(); if (init_child(PROC_TIMER)<0 ) { LM_ERR("init_child failed for timer proc\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(); } else clean_write_pipeend(); run_timer_process( tpl ); exit(-1); } } return 0; error: return -1; }
/** * @brief Initialize async module children */ static int child_init(int rank) { int pid; int i; if (rank==PROC_INIT) { if(evapi_init_notify_sockets()<0) { LM_ERR("failed to initialize notify sockets\n"); return -1; } return 0; } if (rank!=PROC_MAIN) { if(_evapi_dispatcher_pid!=getpid()) { evapi_close_notify_sockets_parent(); } return 0; } pid=fork_process(PROC_NOCHLDINIT, "EvAPI Dispatcher", 1); if (pid<0) return -1; /* error */ if(pid==0) { /* child */ _evapi_dispatcher_pid = getpid(); /* do child init to allow execution of rpc like functions */ if(init_child(PROC_RPC) < 0) { LM_DBG("failed to do RPC child init for dispatcher\n"); return -1; } /* initialize the config framework */ if (cfg_child_init()) return -1; /* main function for dispatcher */ evapi_close_notify_sockets_child(); if(evapi_run_dispatcher(_evapi_bind_addr, _evapi_bind_port)<0) { LM_ERR("failed to initialize evapi dispatcher process\n"); return -1; } } for(i=0; i<_evapi_workers; i++) { pid=fork_process(PROC_RPC, "EvAPI Worker", 1); if (pid<0) return -1; /* error */ if(pid==0) { /* child */ /* initialize the config framework */ if (cfg_child_init()) return -1; /* main function for workers */ if(evapi_run_worker(i+1)<0) { LM_ERR("failed to initialize worker process: %d\n", i); return -1; } } } return 0; }
static void fork_children(void) { int pidslot; static char childname[17]; /* Generate children*/ while (shm->running_childs < shm->max_children) { int pid = 0; /* Find a space for it in the pid map */ pidslot = find_pid_slot(EMPTY_PIDSLOT); if (pidslot == PIDSLOT_NOT_FOUND) { printf("[%d] ## Pid map was full!\n", getpid()); dump_pid_slots(); exit(EXIT_FAILURE); } (void)alarm(0); fflush(stdout); pid = fork(); if (pid != 0) shm->pids[pidslot] = pid; else { /* Child process. */ int ret = 0; mask_signals_child(); memset(childname, 0, sizeof(childname)); sprintf(childname, "trinity-child%d", pidslot); prctl(PR_SET_NAME, (unsigned long) &childname); oom_score_adj(500); /* Wait for parent to set our pidslot */ while (shm->pids[pidslot] != getpid()) { /* Make sure parent is actually alive to wait for us. */ ret = pid_alive(shm->parentpid); if (ret != 0) { shm->exit_reason = EXIT_SHM_CORRUPTION; printf("[%d] " BUGTXT "parent (%d) went away!\n", getpid(), shm->parentpid); sleep(20000); } } init_child(pidslot); ret = child_process(pidslot); output(1, "child %d exiting\n", getpid()); _exit(ret); } shm->running_childs++; debugf("[%d] Created child %d in pidslot %d [total:%d/%d]\n", getpid(), shm->pids[pidslot], pidslot, shm->running_childs, shm->max_children); if (shm->exit_reason != STILL_RUNNING) return; } debugf("[%d] created enough children\n", getpid()); }
/* main loop */ int main_loop() { int i; pid_t pid; struct socket_info* si; #ifdef USE_TCP int sockfd[2]; #endif /* one "main" process and n children handling i/o */ is_main=0; if (dont_fork){ #ifdef STATS setstats( 0 ); #endif if (udp_listen==0){ LOG(L_ERR, "ERROR: 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){ LOG(L_WARN, "WARNING: using only the first listen address" " (no fork)\n"); } /* initialize fifo server -- we need to open the fifo before * do_suid() and start the fifo server after all the socket * are initialized, to inherit them*/ if (init_fifo_server()<0) { LOG(L_ERR, "initializing fifo server failed\n"); goto error; } /* Initialize Unix domain socket server */ if (init_unixsock_socket()<0) { LOG(L_ERR, "Error while creating unix domain sockets\n"); goto error; } if (do_suid()==-1) goto error; /* try to drop privileges */ /* process_no now initialized to zero -- increase from now on as new processes are forked (while skipping 0 reserved for main */ /* we need another process to act as the timer*/ #ifdef USE_TCP /* if we are using tcp we always need a timer process, * we cannot count on select timeout to measure time * (it works only on linux) */ if ((!tcp_disable)||(timer_list)) #else if (timer_list) #endif { process_no++; if ((pid=fork())<0){ LOG(L_CRIT, "ERROR: main_loop: Cannot fork\n"); goto error; } if (pid==0){ /* child */ /* timer!*/ /* process_bit = 0; */ if (init_child(PROC_TIMER) < 0) { LOG(L_ERR, "timer: init_child failed\n"); goto error; } for(;;){ sleep(TIMER_TICK); timer_ticker(); } }else{ pt[process_no].pid=pid; /*should be shared mem anyway*/ strncpy(pt[process_no].desc, "timer", MAX_PT_DESC ); } } /* if configured, start a server for accepting FIFO commands, * we need to do it after all the sockets are initialized, to * inherit them*/ if (start_fifo_server()<0) { LOG(L_ERR, "starting fifo server failed\n"); goto error; } if (init_unixsock_children()<0) { LOG(L_ERR, "Error while initializing Unix domain socket server\n"); goto error; } /* main process, receive loop */ process_no=0; /*main process number*/ pt[process_no].pid=getpid(); snprintf(pt[process_no].desc, MAX_PT_DESC, "stand-alone receiver @ %s:%s", bind_address->name.s, bind_address->port_no_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) { LOG(L_ERR, "main_dontfork: init_child failed\n"); goto error; } is_main=1; /* hack 42: call init_child with is_main=0 in case some modules wants to fork a child */ return udp_rcv_loop(); }else{ /* process_no now initialized to zero -- increase from now on as new processes are forked (while skipping 0 reserved for main ) */ 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 */ /* initialize fifo server -- we need to open the fifo before * do_suid() and start the fifo server after all the socket * are initialized, to inherit them*/ if (init_fifo_server()<0) { LOG(L_ERR, "initializing fifo server failed\n"); goto error; } /* Initialize Unix domain socket server */ /* Create the unix domain sockets */ if (init_unixsock_socket()<0) { LOG(L_ERR, "ERROR: Could not create unix domain sockets\n"); goto error; } /* all processes should have access to all the sockets (for sending) * so we open all first*/ if (do_suid()==-1) goto error; /* try to drop privileges */ /* if configured, start a server for accepting FIFO commands, * we need to do it after all the sockets are initialized, to * inherit them*/ if (start_fifo_server()<0) { LOG(L_ERR, "starting fifo server failed\n"); goto error; } /* Spawn children listening on unix domain socket if and only if * the unix domain socket server has not been disabled (i == 0) */ if (init_unixsock_children()<0) { LOG(L_ERR, "ERROR: Could not initialize unix domain socket server\n"); goto error; } /* udp processes */ for(si=udp_listen; si; si=si->next){ for(i=0;i<children_no;i++){ process_no++; #ifdef USE_TCP if(!tcp_disable){ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){ LOG(L_ERR, "ERROR: main_loop: socketpair failed: %s\n", strerror(errno)); goto error; } } #endif if ((pid=fork())<0){ LOG(L_CRIT, "main_loop: Cannot fork\n"); goto error; }else if (pid==0){ /* child */ #ifdef USE_TCP if (!tcp_disable){ close(sockfd[0]); unix_tcp_sock=sockfd[1]; } #endif bind_address=si; /* shortcut */ if (init_child(i + 1) < 0) { LOG(L_ERR, "init_child failed\n"); goto error; } #ifdef STATS setstats( i+r*children_no ); #endif return udp_rcv_loop(); }else{ pt[process_no].pid=pid; /*should be in shared mem.*/ snprintf(pt[process_no].desc, MAX_PT_DESC, "receiver child=%d sock= %s:%s", i, si->name.s, si->port_no_str.s ); #ifdef USE_TCP if (!tcp_disable){ close(sockfd[1]); pt[process_no].unix_sock=sockfd[0]; pt[process_no].idx=-1; /* this is not a "tcp" process*/ } #endif } } /*parent*/ /*close(udp_sock)*/; /*if it's closed=>sendto invalid fd errors?*/ } } /*this is the main process*/ bind_address=0; /* main proc -> it shouldn't send anything, */ #ifdef USE_TCP /* if we are using tcp we always need the timer */ if ((!tcp_disable)||(timer_list)) #else if (timer_list) #endif { #ifdef USE_TCP if (!tcp_disable){ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){ LOG(L_ERR, "ERROR: main_loop: socketpair failed: %s\n", strerror(errno)); goto error; } } #endif /* fork again for the attendant process*/ process_no++; if ((pid=fork())<0){ LOG(L_CRIT, "main_loop: cannot fork timer process\n"); goto error; }else if (pid==0){ /* child */ /* is_main=0; */ #ifdef USE_TCP if (!tcp_disable){ close(sockfd[0]); unix_tcp_sock=sockfd[1]; } #endif if (init_child(PROC_TIMER) < 0) { LOG(L_ERR, "timer: init_child failed\n"); goto error; } for(;;){ /* debug: instead of doing something useful */ /* (placeholder for timers, etc.) */ sleep(TIMER_TICK); /* if we received a signal => TIMER_TICK may have not elapsed*/ timer_ticker(); } }else{ pt[process_no].pid=pid; strncpy(pt[process_no].desc, "timer", MAX_PT_DESC ); #ifdef USE_TCP if(!tcp_disable){ close(sockfd[1]); pt[process_no].unix_sock=sockfd[0]; pt[process_no].idx=-1; /* this is not a "tcp" process*/ } #endif } } #ifdef USE_TCP if (!tcp_disable){ /* start tcp & tls receivers */ if (tcp_init_children()<0) goto error; /* start tcp+tls master proc */ process_no++; if ((pid=fork())<0){ LOG(L_CRIT, "main_loop: cannot fork tcp main process\n"); goto error; }else if (pid==0){ /* child */ /* is_main=0; */ if (init_child(PROC_TCP_MAIN) < 0) { LOG(L_ERR, "tcp_main: error in init_child\n"); goto error; } tcp_main_loop(); }else{ pt[process_no].pid=pid; strncpy(pt[process_no].desc, "tcp main process", MAX_PT_DESC ); pt[process_no].unix_sock=-1; pt[process_no].idx=-1; /* this is not a "tcp" process*/ unix_tcp_sock=-1; } } #endif /* main */ pt[0].pid=getpid(); strncpy(pt[0].desc, "attendant", MAX_PT_DESC ); #ifdef USE_TCP if(!tcp_disable){ pt[process_no].unix_sock=-1; pt[process_no].idx=-1; /* this is not a "tcp" process*/ unix_tcp_sock=-1; } #endif /*DEBUG- remove it*/ #ifdef DEBUG fprintf(stderr, "\n% 3d processes (%3d), % 3d children * " "listening addresses + tcp listeners + tls listeners" "+ main + fifo %s\n", process_no+1, process_count(), children_no, (timer_list)?"+ timer":""); for (r=0; r<=process_no; r++){ fprintf(stderr, "% 3d % 5d - %s\n", r, pt[r].pid, pt[r].desc); } #endif process_no=0; /* process_bit = 0; */ is_main=1; if (init_child(PROC_MAIN) < 0) { LOG(L_ERR, "main: error in init_child\n"); goto error; } for(;;){ pause(); handle_sigs(); } /*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; }
int start_module_procs(void) { struct sr_module *m; unsigned int n; unsigned int l; pid_t 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); 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"); if (send_status_code(-1) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); exit(-1); } if (send_status_code(0) < 0) LM_ERR("failed to send status code\n"); clean_write_pipeend(); } 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 open_fifo_server() { char *t; struct stat filestat; int n; #ifdef USE_TCP int sockfd[2]; #endif if (fifo==NULL) { DBG("DBG: open_fifo_server: no fifo will be opened\n"); /* everything is ok, we just do not want to start */ return 1; } if (strlen(fifo)==0) { DBG("DBG: open_fifo_server: fifo disabled\n"); return 1; } DBG("DBG: open_uac_fifo: opening fifo...\n"); n=stat(fifo, &filestat); if (n==0){ /* FIFO exist, delete it (safer) */ if (unlink(fifo)<0){ LOG(L_ERR, "ERROR: open_fifo_server: cannot delete old fifo (%s):" " %s\n", fifo, strerror(errno)); return -1; } }else if (n<0 && errno!=ENOENT){ LOG(L_DBG, "DEBUG: open_fifo_server: FIFO stat failed: %s\n", strerror(errno)); } /* create FIFO ... */ if ((mkfifo(fifo, fifo_mode)<0)) { LOG(L_ERR, "ERROR: open_fifo_server; can't create FIFO: " "%s (mode=%d)\n", strerror(errno), fifo_mode); return -1; } DBG("DEBUG: FIFO created @ %s\n", fifo ); if ((chmod(fifo, fifo_mode)<0)) { LOG(L_ERR, "ERROR: open_fifo_server; can't chmod FIFO: " "%s (mode=%d)\n", strerror(errno), fifo_mode); return -1; } DBG("DEBUG: fifo %s opened, mode=%d\n", fifo, fifo_mode ); time(&up_since); t=ctime(&up_since); if (strlen(t)+1>=MAX_CTIME_LEN) { LOG(L_ERR, "ERROR: open_fifo_server: " "too long date %d\n", (int)strlen(t)); return -1; } memcpy(up_since_ctime,t,strlen(t)+1); #ifdef USE_TCP if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){ LOG(L_ERR, "ERROR: open_fifo_server: socketpair failed: %s\n", strerror(errno)); return -1; } #endif process_no++; fifo_pid=fork(); if (fifo_pid<0) { LOG(L_ERR, "ERROR: open_fifo_server: failure to fork: %s\n", strerror(errno)); return -1; } if (fifo_pid==0) { /* child == FIFO server */ LOG(L_INFO, "INFO: fifo process starting: %d\n", getpid()); /* call per-child module initialization too -- some FIFO commands may need it */ #ifdef USE_TCP close(sockfd[0]); unix_tcp_sock=sockfd[1]; #endif if (init_child(PROC_FIFO) < 0 ) { LOG(L_ERR, "ERROR: open_uac_fifo: init_child failed\n"); return -1; } fifo_read=open(fifo, O_RDONLY, 0); if (fifo_read<0) { LOG(L_ERR, "ERROR: open_uac_fifo: fifo_read did not open: %s\n", strerror(errno)); return -1; } fifo_stream=fdopen(fifo_read, "r" ); if (fifo_stream==NULL) { LOG(L_ERR, "SER: open_uac_fifo: fdopen failed: %s\n", strerror(errno)); return -1; } /* a real server doesn't die if writing to reply fifo fails */ signal(SIGPIPE, SIG_IGN); LOG(L_INFO, "SER: open_uac_fifo: fifo server up at %s...\n", fifo); fifo_server( fifo_stream ); /* never retruns */ } /* dad process */ pt[process_no].pid=fifo_pid; strncpy(pt[process_no].desc, "fifo server", MAX_PT_DESC ); #ifdef USE_TCP close(sockfd[1]); pt[process_no].unix_sock=sockfd[0]; pt[process_no].idx=-1; /* this is not "tcp" process*/ #endif /* make sure the read fifo will not close */ fifo_write=open(fifo, O_WRONLY, 0); if (fifo_write<0) { LOG(L_ERR, "SER: open_uac_fifo: fifo_write did not open: %s\n", strerror(errno)); return -1; } 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; }
/** * 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; }
/** * 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; }
/** * 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; }
static void fork_children(void) { int pidslot; static char childname[17]; /* Generate children*/ while (shm->running_childs < shm->max_children) { int pid = 0; int fd; if (shm->spawn_no_more == TRUE) return; /* a new child means a new seed, or the new child * will do the same syscalls as the one in the pidslot it's replacing. * (special case startup, or we reseed unnecessarily) */ if (shm->ready == TRUE) reseed(); /* Find a space for it in the pid map */ pidslot = find_pid_slot(EMPTY_PIDSLOT); if (pidslot == PIDSLOT_NOT_FOUND) { outputerr("## Pid map was full!\n"); dump_pid_slots(); exit(EXIT_FAILURE); } if (logging == TRUE) { fd = fileno(shm->logfiles[pidslot]); if (ftruncate(fd, 0) == 0) lseek(fd, 0, SEEK_SET); } (void)alarm(0); fflush(stdout); pid = fork(); if (pid != 0) shm->pids[pidslot] = pid; else { /* Child process. */ int ret = 0; mask_signals_child(); memset(childname, 0, sizeof(childname)); sprintf(childname, "trinity-child%d", pidslot); prctl(PR_SET_NAME, (unsigned long) &childname); oom_score_adj(500); /* Wait for parent to set our pidslot */ while (shm->pids[pidslot] != getpid()) { /* Make sure parent is actually alive to wait for us. */ ret = pid_alive(shm->mainpid); if (ret != 0) { shm->exit_reason = EXIT_SHM_CORRUPTION; outputerr(BUGTXT "parent (%d) went away!\n", shm->mainpid); sleep(20000); } } /* Wait for all the children to start up. */ while (shm->ready == FALSE) sleep(1); init_child(pidslot); ret = child_process(pidslot); output(1, "child exiting.\n"); _exit(ret); } shm->running_childs++; debugf("Created child %d in pidslot %d [total:%d/%d]\n", shm->pids[pidslot], pidslot, shm->running_childs, shm->max_children); if (shm->exit_reason != STILL_RUNNING) return; } shm->ready = TRUE; debugf("created enough children\n"); }
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; }
/** * 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; }
int view_orb(GtkWidget* Parent,int argc, char **argv) { GtkWidget* vboxwin; GtkWidget* hboxwin; GtkWidget* handleBoxColorMapGrid; GtkWidget* handleBoxColorMapContours; GtkWidget* handleBoxColorMapPlanesMapped; static gboolean first = TRUE; init_dipole(); if(!first) { if(PrincipalWindow) { gtk_widget_hide(GTK_WIDGET(PrincipalWindow)); gtk_widget_show(GTK_WIDGET(PrincipalWindow)); /* if(argc>1) read_any_file(argv[1]);*/ return 0; } } /* initialisation */ initialise_global_orbitals_variables(); read_opengl_file(); /* Create new top level window. */ PrincipalWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(PrincipalWindow), _("Gabedit : Orbitals/Density/Vibration")); gtk_container_set_reallocate_redraws (GTK_CONTAINER (PrincipalWindow), TRUE); gtk_window_set_default_size (GTK_WINDOW(PrincipalWindow),(gint)(ScreenWidth*0.5),(gint)(ScreenHeight*0.69)); gtk_container_set_border_width(GTK_CONTAINER(PrincipalWindow), 1); init_child(PrincipalWindow,gtk_widget_destroy," Draw Dens. Orb. "); /* g_signal_connect(G_OBJECT(PrincipalWindow),"delete_event",(GCallback)close_window_orb,NULL);*/ g_signal_connect(G_OBJECT(PrincipalWindow), "delete-event",G_CALLBACK(gtk_widget_hide_on_delete), NULL); gtk_window_set_transient_for(GTK_WINDOW(PrincipalWindow),GTK_WINDOW(Parent)); vboxwin = create_vbox(PrincipalWindow); gtk_widget_realize(PrincipalWindow); hboxwin = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX(vboxwin), hboxwin, TRUE, TRUE, 2); gtk_widget_show (hboxwin); if (!NewGLArea(hboxwin)) return 0; create_status_bar_orb(vboxwin); create_status_progress_bar_orb(vboxwin); handleBoxColorMapGrid = create_color_map_show(vboxwin,NULL," Grid "); g_object_set_data(G_OBJECT(PrincipalWindow), "HandleboxColorMapGrid ", handleBoxColorMapGrid); handleBoxColorMapContours = create_color_map_show(vboxwin,NULL, "Contours "); g_object_set_data(G_OBJECT(PrincipalWindow), "HandleboxColorMapContours", handleBoxColorMapContours); handleBoxColorMapPlanesMapped = create_color_map_show(vboxwin,NULL," Planes colorcoded"); g_object_set_data(G_OBJECT(PrincipalWindow), "HandleboxColorMapPlanesMapped", handleBoxColorMapPlanesMapped); set_icone(PrincipalWindow); gtk_widget_show(GTK_WIDGET(PrincipalWindow)); color_map_hide(handleBoxColorMapGrid); color_map_hide(handleBoxColorMapContours); color_map_hide(handleBoxColorMapPlanesMapped); /* if(argc>1) read_any_file(argv[1]);*/ first = FALSE; gtk_window_move(GTK_WINDOW(PrincipalWindow),0,0); InitializeAll(); /*printCoefZlm();*/ return 0; }