Ejemplo n.º 1
0
static void
mln_ipc_fd_handler_worker_send(mln_event_t *ev, int fd, void *data)
{
    mln_tcp_conn_t *conn = &master_conn;
    mln_chain_t *c;
    int ret;

    while ((c = mln_tcp_conn_get_head(conn, M_C_SEND)) != NULL) {
        ret = mln_tcp_conn_send(conn);
        if (ret == M_C_FINISH) {
            continue;
        } else if (ret == M_C_NOTYET) {
            mln_chain_pool_release_all(mln_tcp_conn_remove(conn, M_C_SENT));
            mln_event_set_fd(ev, \
                             mln_tcp_conn_get_fd(conn), \
                             M_EV_SEND|M_EV_APPEND|M_EV_NONBLOCK|M_EV_ONESHOT, \
                             M_EV_UNLIMITED, \
                             NULL, \
                             mln_ipc_fd_handler_worker_send);
            return;
        } else if (ret == M_C_ERROR) {
            mln_log(report, "master process dead!\n");
            exit(127);
        } else {
            mln_log(error, "Shouldn't be here.\n");
            abort();
        }
    }

    mln_chain_pool_release_all(mln_tcp_conn_remove(conn, M_C_SENT));
}
Ejemplo n.º 2
0
void mln_socketpair_close_handler(mln_event_t *ev, mln_fork_t *f, int fd)
{
    mln_event_set_fd(ev, fd, M_EV_CLR, M_EV_UNLIMITED, NULL, NULL);
    enum proc_exec_type etype = f->etype;
    enum proc_state_type stype = f->stype;
    mln_s8ptr_t *args = f->args;
    mln_u32_t n_args = f->n_args;
    if (stype == M_PST_SUP) {
        mln_fork_destroy(f, 0);
        if (etype == M_PET_DFL) {
            int rv = mln_fork_restart(ev);
            if (rv < 0) {
                mln_log(error, "mln_fork_restart() error.\n");
                abort();
            } else if (rv == 0) {
                mln_event_set_break(ev);
            } else {
                mln_log(report, "Child process restart.\n");
            }
        } else {/*M_PET_EXE*/
            if (mln_fork_spawn(stype, args, n_args, ev) < 0) {
                mln_log(error, "mln_fork_spawn() error.\n");
                abort();
            }
            mln_log(report, "Process %s restart.\n", args[0]);
        }
    } else {/*M_PST_DFL*/
        mln_fork_destroy(f, 1);
    }
}
Ejemplo n.º 3
0
/*
 * Message Format:
 *     [Length(include type length) 4bytes|type 4bytes|content Nbytes]
 */
void mln_ipc_fd_handler_master(mln_event_t *ev, int fd, void *data)
{
    int ret;
    mln_fork_t *f = (mln_fork_t *)data;
    mln_tcp_conn_t *conn = &(f->conn);

    while (1) {
        ret = mln_tcp_conn_recv(conn, M_C_TYPE_MEMORY);
        if (ret == M_C_FINISH) {
            continue;
        } else if (ret == M_C_NOTYET) {
            break;
        } else if (ret == M_C_CLOSED) {
            mln_log(report, "Child process dead!\n");
            mln_socketpair_close_handler(ev, f, fd);
            return ;
        } else {
            mln_log(error, "recv msg error. %s\n", strerror(errno));
            mln_socketpair_close_handler(ev, f, fd);
            return ;
        }
    }

    mln_ipc_fd_handler_master_process(ev, f);
}
Ejemplo n.º 4
0
int mln_fork_spawn(enum proc_state_type stype, \
                   mln_s8ptr_t *args, \
                   mln_u32_t n_args, \
                   mln_event_t *master_ev)
{
    mln_log(none, "Start up process '%s'\n", args[0]);
    int ret = do_fork_core(M_PET_EXE, \
                           stype, \
                           args, \
                           n_args, \
                           master_ev);
    if (ret < 0) {
        return -1;
    } else if (ret == 0) {
        char fd_str[256] = {0};
        snprintf(fd_str, sizeof(fd_str)-1, "%d", \
                 mln_tcp_conn_get_fd(&master_conn));
        args[n_args] = fd_str;
        if (master_ev != NULL) mln_event_destroy(master_ev);
        mln_log_destroy();
        if (execv(args[0], args) < 0) {
            mln_log(error, "execv error, %s\n", strerror(errno));
            exit(1);
        }
    }
    return 0;
}
Ejemplo n.º 5
0
/*mln_set_worker_ipc_handler*/
void mln_set_worker_ipc_handler(mln_ipc_handler_t *ih)
{
    mln_rbtree_node_t *rn = mln_rbtree_search(worker_ipc_tree, \
                                              worker_ipc_tree->root, \
                                              ih);
    if (rn->data != NULL) {
        mln_log(error, "IPC type '%d' already existed.\n", ih->type);
        abort();
    }
    rn = mln_rbtree_new_node(worker_ipc_tree, ih);
    if (rn == NULL) {
        mln_log(error, "No memory.\n");
        abort();
    }
    mln_rbtree_insert(worker_ipc_tree, rn);
}
Ejemplo n.º 6
0
static void
mln_ipc_fd_handler_master_process(mln_event_t *ev, mln_fork_t *f)
{
    mln_tcp_conn_t *tc = &(f->conn);

    while (1) {
        while (f->error_bytes) {
            f->error_bytes = mln_ipc_discard_bytes(tc, f->error_bytes);
        }
        switch (f->state) {
            case STATE_IDLE:
            {
                if (mln_ipc_get_buf_with_len(tc, &(f->msg_len), M_F_LENLEN) < 0) {
                    return;
                }
                f->state = STATE_LENGTH;
            }
            case STATE_LENGTH:
            {
                if (f->msg_content == NULL) {
                    f->msg_content = malloc(f->msg_len);
                    if (f->msg_content == NULL) {
                        f->error_bytes = f->msg_len;
                        f->state = STATE_IDLE;
                        break;
                    }
                }
                if (mln_ipc_get_buf_with_len(tc, f->msg_content, f->msg_len) < 0) {
                    return;
                }
                memcpy(&(f->msg_type), f->msg_content, M_F_TYPELEN);
                f->state = STATE_IDLE;
                mln_ipc_handler_t ih;
                ih.type = f->msg_type;
                mln_rbtree_node_t *rn = mln_rbtree_search(master_ipc_tree, \
                                                          master_ipc_tree->root, \
                                                          &ih);
                if (!mln_rbtree_null(rn, master_ipc_tree)) {
                    mln_ipc_handler_t *ihp = (mln_ipc_handler_t *)(rn->data);
                    if (ihp->handler != NULL)
                        ihp->handler(ev, \
                                     f, \
                                     f->msg_content+M_F_TYPELEN, \
                                     f->msg_len-M_F_TYPELEN, \
                                     &(ihp->data));
                }
                free(f->msg_content);
                f->msg_content = NULL;
                break;
            }
            default:
                mln_log(error, "No such state!\n");
                abort();
        }
    }
}
Ejemplo n.º 7
0
static void
mln_ipc_fd_handler_worker_process(mln_event_t *ev, mln_tcp_conn_t *tc)
{
    while (1) {
        while (child_error_bytes) {
            child_error_bytes = mln_ipc_discard_bytes(tc, child_error_bytes);
        }
        switch (child_state) {
            case STATE_IDLE:
            {
                if (mln_ipc_get_buf_with_len(tc, &(cur_msg_len), M_F_LENLEN) < 0) {
                    return;
                }
                child_state = STATE_LENGTH;
            }
            case STATE_LENGTH:
            {
                if (child_msg_content == NULL) {
                    child_msg_content = (mln_u8ptr_t)malloc(cur_msg_len);
                    if (child_msg_content == NULL) {
                        child_error_bytes = cur_msg_len;
                        child_state = STATE_IDLE;
                        break;
                    }
                }
                if (mln_ipc_get_buf_with_len(tc, child_msg_content, cur_msg_len) < 0) {
                    return;
                }
                memcpy(&cur_msg_type, child_msg_content, M_F_TYPELEN);
                child_state = STATE_IDLE;
                mln_ipc_handler_t ih;
                ih.type = cur_msg_type;
                mln_rbtree_node_t *rn = mln_rbtree_search(worker_ipc_tree, \
                                                          worker_ipc_tree->root, \
                                                          &ih);
                if (!mln_rbtree_null(rn, worker_ipc_tree)) {
                    mln_ipc_handler_t *ihp = (mln_ipc_handler_t *)(rn->data);
                    if (ihp->handler != NULL)
                        ihp->handler(ev, \
                                     tc, \
                                     child_msg_content+M_F_TYPELEN, \
                                     cur_msg_len-M_F_TYPELEN, \
                                     &(ihp->data));
                }
                free(child_msg_content);
                child_msg_content = NULL;
                break;
            }
            default:
                mln_log(error, "No such state!\n");
                abort();
        }
    }
}
Ejemplo n.º 8
0
void mln_conf_get_cmds(mln_conf_t *cf, char *domain, mln_conf_cmd_t **v)
{
    mln_conf_domain_t *cd = cf->search(cf, domain);
    if (cd == NULL) return;
    struct conf_cmds_scan_s ccs;
    ccs.cc = v;
    ccs.pos = 0;
    if (mln_rbtree_scan_all(cd->cmd, cd->cmd->root, mln_conf_get_cmds_scan, (void *)&ccs) < 0) {
        mln_log(error, "Shouldn't be here.\n");
        abort();
    }
}
Ejemplo n.º 9
0
void mln_ipc_fd_handler_worker(mln_event_t *ev, int fd, void *data)
{
    int ret;
    mln_tcp_conn_t *conn = &master_conn;

    while (1) {
        ret = mln_tcp_conn_recv(conn, M_C_TYPE_MEMORY);
        if (ret == M_C_FINISH) {
            continue;
        } else if (ret == M_C_NOTYET) {
            break;
        } else if (ret == M_C_CLOSED) {
            mln_log(report, "Master process dead!\n");
            exit(127);
        } else {
            mln_log(error, "recv msg error. %s\n", strerror(errno));
            exit(127);
        }
    }

    mln_ipc_fd_handler_worker_process(ev, conn);
}
Ejemplo n.º 10
0
void mln_fork_worker_set_events(mln_event_t *ev)
{
    if (mln_event_set_fd(ev, \
                         mln_tcp_conn_get_fd(&master_conn), \
                         M_EV_RECV|M_EV_NONBLOCK, \
                         M_EV_UNLIMITED, \
                         NULL, \
                         mln_ipc_fd_handler_worker) < 0)
    {
        mln_log(error, "mln_event_set_fd() failed.\n");
        abort();
    }
}
Ejemplo n.º 11
0
static int
do_fork_worker_process(mln_sauto_t n_worker_proc)
{
    mln_sauto_t i;
    int ret;
    for (i = 0; i < n_worker_proc; ++i) {
        mln_log(none, "Start up worker process No.%l\n", i+1);
        if ((ret = mln_fork_restart(NULL)) < 0) {
            continue;
        } else if (ret == 0) {
            return 0;
        }
    }
    return 1;
}
Ejemplo n.º 12
0
/*
 * events
 */
void mln_fork_master_set_events(mln_event_t *ev)
{
    mln_fork_t *f;
    for (f = worker_list_head; f != NULL; f = f->next) {
        if (mln_event_set_fd(ev, \
                             mln_tcp_conn_get_fd(&(f->conn)), \
                             M_EV_RECV|M_EV_NONBLOCK, \
                             M_EV_UNLIMITED, \
                             f, \
                             mln_ipc_fd_handler_master) < 0)
        {
            mln_log(error, "mln_event_set_fd() failed.\n");
            abort();
        }
    }
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
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;
}
Ejemplo n.º 15
0
/*
 * fork processes
 */
int do_fork(void)
{
    mln_conf_t *cf = mln_get_conf();
    if (cf == NULL) {
        mln_log(error, "configuration crashed.\n");
        abort();
    }
    mln_conf_domain_t *cd = cf->search(cf, "main");
    if (cd == NULL) {
        mln_log(error, "Domain 'main' NOT existed.\n");
        abort();
    }
    mln_sauto_t n_worker_proc = 0;
    mln_conf_cmd_t *cmd = cd->search(cd, "worker_proc");
    if (cmd != NULL) {
        if (mln_conf_get_argNum(cmd) > 1) {
            mln_log(error, "Too many arguments follow 'worker_proc'.\n");
            exit(1);
        }
        mln_conf_item_t *ci = cmd->search(cmd, 1);
        if (ci == NULL) {
            mln_log(error, "'worker_proc' need an integer argument.\n");
            exit(1);
        }
        if (ci->type != CONF_INT) {
            mln_log(error, "'worker_proc' need an integer argument.\n");
            exit(1);
        }
        n_worker_proc = ci->val.i;
        if (n_worker_proc < 0) {
            mln_log(error, "Invalid value to 'worker_process'.\n");
            exit(1);
        }
    }
    if (!do_fork_worker_process(n_worker_proc)) return 0;

    mln_conf_cmd_t **v, **cc;
    mln_u32_t i, n_args;
    mln_conf_item_t *arg_ci;
    mln_s8ptr_t *v_args;
    mln_u32_t n = mln_conf_get_cmdNum(cf, "exec_proc");
    if (n == 0) return 1;

    v = (mln_conf_cmd_t **)calloc(n+1, sizeof(mln_conf_cmd_t *));
    if (v == NULL) {
        mln_log(error, "No memory.\n");
        return -1;
    }
    mln_conf_get_cmds(cf, "exec_proc", v);
    for (cc = v; *cc != NULL; ++cc) {
        n_args = mln_conf_get_argNum(*cc);
        if (n_args == 0) {
            mln_log(error, "Demand arguments in 'exec_proc'.\n");
            exit(1);
        }
        v_args = (mln_s8ptr_t *)calloc(n_args+2, sizeof(mln_s8ptr_t));
        if (v_args == NULL) {
            mln_log(error, "No memory.\n");
            continue;
        }
        for (i = 0; i < n_args; ++i) {
            arg_ci = (*cc)->search(*cc, i+1);
            if (arg_ci->type != CONF_STR) {
                mln_log(error, "Demand string arguments in 'exec_proc'.\n");
                exit(1);
            }
            v_args[i] = (char *)(arg_ci->val.s->data);
        }
        if (!mln_string_constStrcmp((*cc)->cmd_name, "keepalive")) {
            mln_fork_spawn(M_PST_SUP, v_args, n_args, NULL);
        } else if (!mln_string_constStrcmp((*cc)->cmd_name, "default")) {
            mln_fork_spawn(M_PST_DFL, v_args, n_args, NULL);
        } else {
            mln_log(error, "Invalid command '%S' in 'exec_proc'.\n", (*cc)->cmd_name);
            exit(1);
        }
    }
    free(v);
    return 1;
}
Ejemplo n.º 16
0
static inline int
mln_Allocator_init(mln_salloc_t **sa)
{
    if (*sa != NULL) return 0;
    int err = 0;
#ifdef MAP_ANONYMOUS
    *sa = (mln_salloc_t *)mmap(NULL, \
                               sizeof(mln_salloc_t), \
                               PROT_READ|PROT_WRITE, \
                               MAP_PRIVATE|MAP_ANONYMOUS, \
                               -1, 0);
#else
    *sa = (mln_salloc_t *)mmap(NULL, \
                               sizeof(mln_salloc_t), \
                               PROT_READ|PROT_WRITE, \
                               MAP_PRIVATE|MAP_ANON, \
                               -1, 0);
#endif
    if (*sa == MAP_FAILED) {
        mln_log(error, "Allocator init failed. %s\n", strerror(errno));
        return -1;
    }

    mln_index_table_init((*sa)->index_tbl);
    (*sa)->current_size = 0;
    (*sa)->threshold = 0;
    err = MLN_LOCK_INIT(&((*sa)->index_lock));
    if (err != 0) {
        mln_log(error, "index_lock init error. %s\n", strerror(err));
        goto err1;
    }
    err = MLN_LOCK_INIT(&((*sa)->stat_lock));
    if (err != 0) {
        mln_log(error, "stat_lock init error. %s\n", strerror(err));
        goto err2;
    }

    if (sa != &mAllocator) {
        MLN_LOCK(&mMiscLock);
        if (!mForkSet) {
            if ((err = pthread_atfork(mln_sa_atfork_prepare, \
                                      mln_sa_atfork_parent, \
                                      mln_sa_atfork_child)) != 0)
            {
                mln_log(error, "pthread_atfork error. %s\n", strerror(err));
                MLN_UNLOCK(&mMiscLock);
                goto err3;
            }
            mForkSet = 1;
        }
        if (!mKeyInit) {
            if ((err = pthread_key_create(&mKey, mln_move)) != 0) {
                mln_log(error, "pthread_key_create error. %s\n", strerror(err));
                MLN_UNLOCK(&mMiscLock);
                goto err3;
            }
            mKeyInit = 1;
        }
        if ((err = pthread_setspecific(mKey, *sa)) != 0) {
            mln_log(error, "pthread_setspecific error. %s\n", strerror(err));
            if (mRef == 0) {
                pthread_key_delete(mKey);
                mKeyInit = 0;
            }
            MLN_UNLOCK(&mMiscLock);
            goto err3;
        }
        ++mRef;
        sa_q_chain_add(&mAHead, &mATail, *sa);
        MLN_UNLOCK(&mMiscLock);
        return 0;
    }

    mPageSize = sysconf(_SC_PAGESIZE);
    if (mPageSize < 0) {
        mPageSize = M_DFL_PAGESIZE;
    }
    
    mLargeTree.nil.data = NULL;
    mLargeTree.nil.parent = &(mLargeTree.nil);
    mLargeTree.nil.left = &(mLargeTree.nil);
    mLargeTree.nil.right = &(mLargeTree.nil);
    mLargeTree.nil.color = M_SARB_BLACK;
    mLargeTree.root = &(mLargeTree.nil);
    mLargeTree.cmp = mln_large_tree_cmp;

    err = MLN_LOCK_INIT(&mHeapLock);
    if (err != 0) {
        mln_log(error, "mHeapLock init error. %s\n", strerror(err));
        goto err3;
    }
    err = MLN_LOCK_INIT(&mLargeTreeLock);
    if (err != 0) {
        mln_log(error, "mLargeTreeLock init error. %s\n", strerror(err));
        goto err4;
    }
    err = MLN_LOCK_INIT(&mMmapLock);
    if (err != 0) {
        mln_log(error, "mMmapLock init error. %s\n", strerror(err));
        goto err5;
    }
    err = MLN_LOCK_INIT(&mMiscLock);
    if (err != 0) {
        mln_log(error, "mMiscLock init error. %s\n", strerror(err));
        goto err6;
    }

    return 0;

err6:
    MLN_LOCK_DESTROY(&mMmapLock);
err5:
    MLN_LOCK_DESTROY(&mLargeTreeLock);
err4:
    MLN_LOCK_DESTROY(&mHeapLock);
err3:
    MLN_LOCK_DESTROY(&((*sa)->stat_lock));
err2:
    MLN_LOCK_DESTROY(&((*sa)->index_lock));
err1:
    munmap((*sa), sizeof(mln_salloc_t));
    *sa = NULL;
    return -1;
}