예제 #1
0
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);
}
예제 #2
0
/*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;
}
예제 #3
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);
}
예제 #4
0
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;
}
예제 #5
0
    /*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;
}