📄 perchild.c
字号:
iov.iov_len = 0; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; cmsg = apr_palloc(r->pool, sizeof(*cmsg) + sizeof(sfd)); cmsg->cmsg_len = sizeof(*cmsg) + sizeof(int); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; memcpy(CMSG_DATA(cmsg), &sfd, sizeof(sfd)); msg.msg_control = (caddr_t)cmsg; msg.msg_controllen = cmsg->cmsg_len; msg.msg_flags=0; if (sendmsg(sconf->sd2, &msg, 0) == -1) { apr_pool_destroy(r->pool); return -1; } write(sconf->sd2, foo, len); while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING) == APR_SUCCESS) { apr_bucket *e; APR_BRIGADE_FOREACH(e, bb) { const char *str; apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ); write(sconf->sd2, str, len); } } apr_pool_destroy(r->pool); return 1;}static char *make_perchild_socket(const char *fullsockname, int sd[2]){ socketpair(PF_UNIX, SOCK_STREAM, 0, sd); return NULL;}static void perchild_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s){ int i; server_rec *sr; perchild_server_conf *sconf; int def_sd[2]; def_sd[0] = -1; def_sd[1] = -1; for (sr = s; sr; sr = sr->next) { sconf = (perchild_server_conf *)ap_get_module_config(sr->module_config, &mpm_perchild_module); if (sconf->sd == -1) { sconf->fullsockname = apr_pstrcat(sr->process->pool, sconf->sockname, ".DEFAULT", NULL); if (def_sd[0] == -1) { if (!make_perchild_socket(sconf->fullsockname, def_sd)) { /* log error */ } } sconf->sd = def_sd[0]; sconf->sd2 = def_sd[1]; } } for (i = 0; i < num_daemons; i++) { if (child_info_table[i].uid == -1) { child_info_table[i].sd = def_sd[0]; } }}static int perchild_post_read(request_rec *r){ ap_filter_t *f = r->connection->input_filters; int thread_num = r->connection->id % HARD_THREAD_LIMIT; perchild_server_conf *sconf = (perchild_server_conf *) ap_get_module_config(r->server->module_config, &mpm_perchild_module); while (f) { if (!strcmp("PERCHILD_BUFFER", f->frec->name)) { ap_remove_output_filter(f); break; } f = f->next; } if (thread_socket_table[thread_num] != -1) { apr_socket_t *csd = NULL; apr_os_sock_put(&csd, &thread_socket_table[thread_num], r->connection->pool); ap_sock_disable_nagle(csd); r->connection->client_socket = csd; return OK; } else { if (sconf->sd != child_info_table[child_num].sd) { if (pass_request(r) == -1) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, ap_server_conf, "Could not pass request to proper " "child, request will not be honored."); } longjmp(jmpbuffer, 1); } return OK; } return OK;}static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode){ apr_bucket *e; apr_status_t rv; char *buffer = NULL; const char *str; apr_size_t len; if ((rv = ap_get_brigade(f->next, b, mode)) != APR_SUCCESS) { return rv; } apr_pool_userdata_get((void **)&buffer, "PERCHILD_BUFFER", f->c->pool); APR_BRIGADE_FOREACH(e, b) { if (e->length != 0) { apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ); if (buffer == NULL) { buffer = apr_pstrndup(f->c->pool, str, len); } else { buffer = apr_pstrcat(f->c->pool, buffer, apr_pstrndup(f->c->pool, str, len), NULL); } } } apr_pool_userdata_set(buffer, "PERCHILD_BUFFER", apr_pool_cleanup_null, f->c->pool); return APR_SUCCESS;}static int perchild_pre_connection(conn_rec *c){ ap_add_input_filter("PERCHILD_BUFFER", NULL, NULL, c); return OK;}static void perchild_hooks(apr_pool_t *p){ one_process = 0; ap_hook_pre_config(perchild_pre_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_config(perchild_post_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_pre_connection(perchild_pre_connection,NULL,NULL, APR_HOOK_MIDDLE); /* This must be run absolutely first. If this request isn't for this * server then we need to forward it to the proper child. No sense * tying up this server running more post_read request hooks if it is * just going to be forwarded along. */ ap_hook_post_read_request(perchild_post_read, NULL, NULL, APR_HOOK_REALLY_FIRST); ap_register_input_filter("PERCHILD_BUFFER", perchild_buffer, AP_FTYPE_CONTENT);}static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg) { const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } if (cmd->server->is_virtual) { return "PidFile directive not allowed in <VirtualHost>"; } ap_pid_fname = arg; return NULL;}static const char *set_scoreboard(cmd_parms *cmd, void *dummy, const char *arg){ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } ap_scoreboard_fname = arg; return NULL;}static const char *set_lockfile(cmd_parms *cmd, void *dummy, const char *arg) { const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } lock_fname = arg; return NULL;}static const char *set_num_daemons (cmd_parms *cmd, void *dummy, const char *arg) { const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } num_daemons = atoi(arg); if (num_daemons > HARD_SERVER_LIMIT) { ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: NumServers of %d exceeds compile time limit " "of %d servers,", num_daemons, HARD_SERVER_LIMIT); ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " lowering NumServers to %d. To increase, please " "see the", HARD_SERVER_LIMIT); ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " HARD_SERVER_LIMIT define in %s.", AP_MPM_HARD_LIMITS_FILE); num_daemons = HARD_SERVER_LIMIT; } else if (num_daemons < 1) { ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: Require NumServers > 0, setting to 1"); num_daemons = 1; } return NULL;}static const char *set_threads_to_start (cmd_parms *cmd, void *dummy, const char *arg) { const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } threads_to_start = atoi(arg); if (threads_to_start > HARD_THREAD_LIMIT) { ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: StartThreads of %d exceeds compile time" " limit of %d threads,", threads_to_start, HARD_THREAD_LIMIT); ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " lowering StartThreads to %d. To increase, please" " see the", HARD_THREAD_LIMIT); ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " HARD_THREAD_LIMIT define in %s.", AP_MPM_HARD_LIMITS_FILE); } else if (threads_to_start < 1) { ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: Require StartThreads > 0, setting to 1"); threads_to_start = 1; } return NULL;}static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, const char *arg){ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } min_spare_threads = atoi(arg); if (min_spare_threads <= 0) { ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: detected MinSpareThreads set to non-positive."); ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Resetting to 1 to avoid almost certain Apache failure."); ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Please read the documentation."); min_spare_threads = 1; } return NULL;}static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy, const char *arg){ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } max_spare_threads = atoi(arg); if (max_spare_threads >= HARD_THREAD_LIMIT) { ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: detected MinSpareThreads set higher than"); ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT); max_spare_threads = HARD_THREAD_LIMIT; } return NULL;}static const char *set_max_threads(cmd_parms *cmd, void *dummy, const char *arg){ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } max_threads = atoi(arg); if (max_threads > HARD_THREAD_LIMIT) { ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: detected MaxThreadsPerChild set higher than"); ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT); max_threads = HARD_THREAD_LIMIT; } return NULL;}static const char *set_max_requests(cmd_parms *cmd, void *dummy, const char *arg) { const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } max_requests_per_child = atoi(arg); return NULL;}static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, const char *arg) { apr_finfo_t finfo; const char *fname; const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } fname = ap_server_root_relative(cmd->pool, arg); if ((apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool) != APR_SUCCESS) || (finfo.filetype != APR_DIR)) { return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname, " does not exist or is not a directory", NULL); } apr_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir)); return NULL;}static const char *set_child_per_uid(cmd_parms *cmd, void *dummy, const char *u, const char *g, const char *num){ int i; int max_this_time = atoi(num) + curr_child_num; for (i = curr_child_num; i < max_this_time; i++, curr_child_num++); { child_info_t *ug = &child_info_table[i - 1]; if (i > num_daemons) { return "Trying to use more child ID's than NumServers. Increase " "NumServers in your config file."; } ug->uid = atoi(u); ug->gid = atoi(g); } return NULL;}static const char *assign_childuid(cmd_parms *cmd, void *dummy, const char *uid, const char *gid){ int i; int u = atoi(uid); int g = atoi(gid); const char *errstr; int socks[2]; perchild_server_conf *sconf = (perchild_server_conf *) ap_get_module_config(cmd->server->module_config, &mpm_perchild_module); sconf->fullsockname = apr_pstrcat(cmd->pool, sconf->sockname, ".", uid, ":", gid, NULL); if ((errstr = make_perchild_socket(sconf->fullsockname, socks))) { return errstr; } sconf->sd = socks[0]; sconf->sd2 = socks[1]; for (i = 0; i < num_daemons; i++) { if (u == child_info_table[i].uid && g == child_info_table[i].gid) { child_info_table[i].sd = sconf->sd; } } return NULL;}static const command_rec perchild_cmds[] = {UNIX_DAEMON_COMMANDSLISTEN_COMMANDSAP_INIT_TAKE1("PidFile", set_pidfile, NULL, RSRC_CONF, "A file for logging the server process ID"),AP_INIT_TAKE1("ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF, "A file for Apache to maintain runtime process management information"),AP_INIT_TAKE1("LockFile", set_lockfile, NULL, RSRC_CONF, "The lockfile used when Apache needs to lock the accept() call"),AP_INIT_TAKE1("NumServers", set_num_daemons, NULL, RSRC_CONF, "Number of children alive at the same time"),AP_INIT_TAKE1("StartThreads", set_threads_to_start, NULL, RSRC_CONF, "Number of threads each child creates"),AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF, "Minimum number of idle threads per child, to handle request spikes"),AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF, "Maximum number of idle threads per child"),AP_INIT_TAKE1("MaxThreadsPerChild", set_max_threads, NULL, RSRC_CONF, "Maximum number of threads per child"),AP_INIT_TAKE1("MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, "Maximum number of requests a particular child serves before dying."),AP_INIT_TAKE1("CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF, "The location of the directory Apache changes to before dumping core"),AP_INIT_TAKE3("ChildperUserID", set_child_per_uid, NULL, RSRC_CONF, "Specify a User and Group for a specific child process."),AP_INIT_TAKE2("AssignUserID", assign_childuid, NULL, RSRC_CONF, "Tie a virtual host to a specific child process."),{ NULL }};static void *perchild_create_config(apr_pool_t *p, server_rec *s){ perchild_server_conf *c = (perchild_server_conf *) apr_pcalloc(p, sizeof(perchild_server_conf)); c->sd = -1; return c;}module AP_MODULE_DECLARE_DATA mpm_perchild_module = { MPM20_MODULE_STUFF, NULL, /* hook to run before apache parses args */ NULL, /* create per-directory config structure */ NULL, /* merge per-directory config structures */ perchild_create_config, /* create per-server config structure */ NULL, /* merge per-server config structures */ perchild_cmds, /* command apr_table_t */ perchild_hooks /* register_hooks */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -