static void mln_conf_destroy(mln_conf_t *cf) { if (cf == NULL) return; mln_conf_destroy_lex(cf); if (cf->domain != NULL) { mln_rbtree_destroy(cf->domain); cf->domain = NULL; } free(cf); }
/*pre-fork*/ int mln_pre_fork(void) { if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { mln_log(error, "signal() to ignore SIGCHLD failed, %s\n", strerror(errno)); return -1; } if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { mln_log(error, "signal() to ignore SIGPIPE failed, %s\n", strerror(errno)); return -1; } struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = do_fork_sig_handler; sigemptyset(&(act.sa_mask)); sigfillset(&(act.sa_mask)); if (sigaction(wait_signo, &act, NULL) < 0) { mln_log(error, "sigaction error, signo:%d. %s\n", \ wait_signo, strerror(errno)); return -1; } if (mln_tcp_conn_init(&master_conn, -1) < 0) { mln_log(error, "No memory.\n"); return -1; } child_state = STATE_IDLE; child_error_bytes = 0; cur_msg_len = 0; child_msg_content = NULL; cur_msg_type = 0; struct mln_rbtree_attr rbattr; rbattr.cmp = mln_fork_rbtree_cmp; rbattr.data_free = NULL; if ((master_ipc_tree = mln_rbtree_init(&rbattr)) < 0) { mln_log(error, "No memory.\n"); if (mln_tcp_conn_get_fd(&master_conn) >= 0) close(mln_tcp_conn_get_fd(&master_conn)); mln_tcp_conn_destroy(&master_conn); return -1; } if ((worker_ipc_tree = mln_rbtree_init(&rbattr)) < 0) { mln_log(error, "No memory.\n"); mln_rbtree_destroy(master_ipc_tree); master_ipc_tree = NULL; if (mln_tcp_conn_get_fd(&master_conn) >= 0) close(mln_tcp_conn_get_fd(&master_conn)); mln_tcp_conn_destroy(&master_conn); return -1; } mln_set_ipc_handlers(); return 0; }
static void mln_conf_domain_destroy(void *data) { if (data == NULL) return; mln_conf_domain_t *cd = (mln_conf_domain_t *)data; if (cd->domain_name != NULL) { mln_string_free(cd->domain_name); cd->domain_name = NULL; } if (cd->cmd != NULL) { mln_rbtree_destroy(cd->cmd); cd->cmd = NULL; } free(cd); }
static int do_fork_core(enum proc_exec_type etype, \ enum proc_state_type stype, \ mln_s8ptr_t *args, \ mln_u32_t n_args, \ mln_event_t *master_ev) { int fds[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { mln_log(error, "socketpair() error. %s\n", strerror(errno)); return -1; } pid_t pid = fork(); if (pid > 0) { close(fds[1]); /* * In linux 2.6.32-279, there is a loophole in process restart. * If you use select() or kqueue(), you wouldn't get this problem. * If I don't add a signal to make parent process wait for child, * the event which combined with the fd that * created by socketpair() and used to receive child process messages * would be tiggered by epoll_wait() with an empty receive buffer. * If fd is blocking model, the parent routine would be blocked * in read(). Because there is a moment that child process not be built yet, * but parent process have already added the fd into the epoll and * jump into the mln_event_dispatch(). * And then, child process built, that would make the event * which is triggered in parent process to be a lie. */ while (child_startup == 0) ; child_startup = 0; struct mln_fork_attr fattr; fattr.args = args; fattr.n_args = n_args; fattr.fd = fds[0]; fattr.pid = pid; fattr.etype = etype; fattr.stype = stype; mln_fork_t *f = mln_fork_init(&fattr); if (f == NULL) { mln_log(error, "No memory.\n"); abort(); } if (master_ev != NULL) { if (mln_event_set_fd(master_ev, \ mln_tcp_conn_get_fd(&(f->conn)), \ M_EV_RECV, \ M_EV_UNLIMITED, \ f, \ mln_ipc_fd_handler_master) < 0) { mln_log(error, "mln_event_set_fd() failed.\n"); abort(); } } return 1; } else if (pid == 0) { close(fds[0]); mln_fork_destroy_all(); mln_rbtree_destroy(master_ipc_tree); if (rs_clr_handler != NULL) rs_clr_handler(rs_clr_data); master_ipc_tree = NULL; mln_tcp_conn_set_fd(&master_conn, fds[1]); signal(SIGCHLD, SIG_DFL); signal(wait_signo, SIG_DFL); if (kill(getppid(), wait_signo) < 0) { mln_log(error, "kill() error. %s\n", strerror(errno)); abort(); } return 0; } mln_log(error, "fork() error. %s\n", strerror(errno)); return -1; }
/*mln_conf_t*/ static inline mln_conf_t *mln_conf_init(void) { mln_conf_lex_lex_dup(NULL, NULL);/*nothing to do, just get rid of compiler's warnging*/ mln_conf_t *cf; mln_rbtree_node_t *rn; cf = (mln_conf_t *)malloc(sizeof(mln_conf_t)); if (cf == NULL) { fprintf(stderr, "No memory.\n"); return NULL; } cf->search = mln_conf_search_domain; struct mln_rbtree_attr rbattr; rbattr.cmp = mln_conf_domain_cmp; rbattr.data_free = mln_conf_domain_destroy; if ((cf->domain = mln_rbtree_init(&rbattr)) == NULL) { fprintf(stderr, "No memory.\n"); free(cf); return NULL; } mln_alloc_t *pool; mln_string_t path; char *conf_file_path; mln_size_t path_len = strlen(mln_path()); mln_lex_hooks_t hooks; struct mln_lex_attr lattr; if ((pool = mln_alloc_init()) == NULL) { fprintf(stderr, "No memory.\n"); mln_rbtree_destroy(cf->domain); free(cf); return NULL; } if ((conf_file_path = (char *)mln_alloc_m(pool, path_len + sizeof(conf_filename) + 1)) == NULL) { fprintf(stderr, "No memory.\n"); mln_alloc_destroy(pool); mln_rbtree_destroy(cf->domain); free(cf); return NULL; } memcpy(conf_file_path, mln_path(), path_len); conf_file_path[path_len] = '/'; memcpy(conf_file_path+path_len+1, conf_filename, sizeof(conf_filename)-1); mln_string_nSet(&path, conf_file_path, path_len + sizeof(conf_filename)); lattr.pool = pool; lattr.keywords = conf_keywords; memset(&hooks, 0, sizeof(hooks)); hooks.slash_handler = (lex_hook)mln_conf_lex_slash_handler; hooks.sglq_handler = (lex_hook)mln_conf_lex_sglq_handler; hooks.dblq_handler = (lex_hook)mln_conf_lex_dblq_handler; lattr.hooks = &hooks; lattr.preprocess = 1; lattr.type = M_INPUT_T_FILE; lattr.data = &path; mln_lex_initWithHooks(mln_conf_lex, cf->lex, &lattr); mln_alloc_free(conf_file_path); if (cf->lex == NULL) { fprintf(stderr, "No memory.\n"); mln_alloc_destroy(pool); mln_rbtree_destroy(cf->domain); free(cf); return NULL; } mln_conf_domain_t *cd = mln_conf_domain_init(cf, &default_domain); if (cd == NULL) { fprintf(stderr, "No memory.\n"); mln_conf_destroy(cf); return NULL; } if ((rn = mln_rbtree_new_node(cf->domain, cd)) == NULL) { fprintf(stderr, "No memory.\n"); mln_conf_domain_destroy((void *)cd); mln_conf_destroy(cf); return NULL; } mln_rbtree_insert(cf->domain, rn); return cf; }