📄 perchild.c
字号:
h.p = r->pool; h.headers = apr_pstrcat(h.p, r->the_request, CRLF, "Host: ", r->hostname, CRLF, NULL); apr_table_do((int (*) (void *, const char *, const char *)) perchild_header_field, (void *) &h, r->headers_in, NULL); h.headers = apr_pstrcat(h.p, h.headers, CRLF, NULL); iov[0].iov_base = h.headers; iov[0].iov_len = strlen(h.headers) + 1; iov[1].iov_base = request_body; iov[1].iov_len = l + 1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 2; cmsg = apr_palloc(r->pool, sizeof(*cmsg) + sizeof(sfd)); cmsg->cmsg_len = sizeof(*cmsg) + sizeof(sfd); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; memcpy(CMSG_DATA(cmsg), &sfd, sizeof(sfd)); msg.msg_control = cmsg; msg.msg_controllen = cmsg->cmsg_len; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "Writing message to %d, passing sd: %d", sconf->output, sfd); if ((rv = sendmsg(sconf->output, &msg, 0)) == -1) { apr_pool_destroy(r->pool); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "Writing message failed %d %d", rv, errno); return -1; } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "Writing message succeeded %d", rv); 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 int 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->input == -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->input = def_sd[0]; sconf->output = def_sd[1]; } } for (i = 0; i < num_daemons; i++) { if (child_info_table[i].uid == -1) { child_info_table[i].input = def_sd[0]; child_info_table[i].output = def_sd[1]; } } thread_socket_table = (int *)apr_pcalloc(p, thread_limit * sizeof(int)); for (i = 0; i < thread_limit; i++) { thread_socket_table[i] = AP_PERCHILD_THISCHILD; } ap_child_table = (ap_ctable *)apr_pcalloc(p, server_limit * sizeof(ap_ctable)); return OK;}static int perchild_post_read(request_rec *r){ int thread_num = r->connection->id % thread_limit; perchild_server_conf *sconf = (perchild_server_conf *) ap_get_module_config(r->server->module_config, &mpm_perchild_module); if (thread_socket_table[thread_num] != AP_PERCHILD_THISCHILD) { apr_socket_t *csd = NULL; apr_os_sock_put(&csd, &thread_socket_table[thread_num], r->connection->pool); ap_sock_disable_nagle(csd); ap_set_module_config(r->connection->conn_config, &core_module, csd); return OK; } else { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "Determining if request should be passed. " "Child Num: %d, SD: %d, sd from table: %d, hostname from server: %s", child_num, sconf->input, child_info_table[child_num].input, r->server->server_hostname); /* sconf is the server config for this vhost, so if our socket * is not the same that was set in the config, then the request * needs to be passed to another child. */ if (sconf->input != child_info_table[child_num].input) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "Passing request."); if (pass_request(r) == -1) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "Could not pass request to proper " "child, request will not be honored."); } longjmp(jmpbuffer, 1); } return OK; } return OK;}static void perchild_hooks(apr_pool_t *p){ /* The perchild open_logs phase must run before the core's, or stderr * will be redirected to a file, and the messages won't print to the * console. */ static const char *const aszSucc[] = {"core.c", NULL}; one_process = 0; ap_hook_open_logs(perchild_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE); ap_hook_pre_config(perchild_pre_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_config(perchild_post_config, NULL, NULL, APR_HOOK_MIDDLE); /* Both of these 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. The process_connection hook allows * perchild to receive the passed request correctly, by automatically * filling in the core_input_filter's ctx pointer. */ ap_hook_post_read_request(perchild_post_read, NULL, NULL, APR_HOOK_REALLY_FIRST); ap_hook_process_connection(perchild_process_connection, NULL, NULL, APR_HOOK_REALLY_FIRST);}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 > server_limit) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "WARNING: NumServers of %d exceeds ServerLimit value " "of %d servers,", num_daemons, server_limit); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, " lowering NumServers to %d. To increase, please " "see the", server_limit); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, " ServerLimit directive."); num_daemons = server_limit; } else if (num_daemons < 1) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 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 > thread_limit) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "WARNING: StartThreads of %d exceeds ThreadLimit value" " of %d threads,", threads_to_start, thread_limit); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, " lowering StartThreads to %d. To increase, please" " see the", thread_limit); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, " ThreadLimit directive."); } else if (threads_to_start < 1) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 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, 0, NULL, "WARNING: detected MinSpareThreads set to non-positive."); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "Resetting to 1 to avoid almost certain Apache failure."); ap_log_error(APLOG_MARK, APLOG_STARTUP, 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 >= thread_limit) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "WARNING: detected MinSpareThreads set higher than"); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "ThreadLimit. Resetting to %d", thread_limit); max_spare_threads = 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 > thread_limit) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "WARNING: detected MaxThreadsPerChild set higher than"); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "ThreadLimit. Resetting to %d", thread_limit); max_threads = thread_limit; } 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++) { if (i > num_daemons) { return "Trying to use more child ID's than NumServers. Increase " "NumServers in your config file."; } child_info_table[i].uid = ap_uname2id(u); child_info_table[i].gid = ap_gname2id(g); #ifndef BIG_SECURITY_HOLE if (child_info_table[i].uid == 0 || child_info_table[i].gid == 0) { return "Assigning root user/group to a child."; }#endif } return NULL;}static const char *assign_childuid(cmd_parms *cmd, void *dummy, const char *uid, const char *gid){ int i; int matching = 0; int u = ap_uname2id(uid); int g = ap_gname2id(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->input = socks[0]; sconf->output = 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].input = sconf->input; child_info_table[i].output = sconf->output; matching++; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, "filling out child_info_table; UID: %d, GID: %d, " "SD: %d %d, OUTPUT: %d %d, Child Num: %d", child_info_table[i].uid, child_info_table[i].gid, sconf->input, child_info_table[i].input, sconf->output, child_info_table[i].output, i); } } if (!matching) { return "Unable to find process with matching uid/gid."; } return NULL;}static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) { int tmp_server_limit; const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } tmp_server_limit = atoi(arg); /* you cannot change ServerLimit across a restart; ignore * any such attempts */ if (first_server_limit && tmp_server_limit != server_limit) { /* how do we log a message? the error log is a bit bucket at this * point; we'll just have to set a flag so that ap_mpm_run() * logs a warning later */ changed_limit_at_restart = 1; return NULL; } server_limit = tmp_server_limit; if (server_limit > MAX_SERVER_LIMIT) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "WARNING: ServerLimit of %d exceeds compile time limit " "of %d servers,", server_limit, MAX_SERVER_LIMIT); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, " lowering ServerLimit to %d.", MAX_SERVER_LIMIT); server_limit = MAX_SERVER_LIMIT; } else if (server_limit < 1) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "WARNING: Require ServerLimit > 0, setting to 1"); server_limit = 1; } return NULL;}static const char *set_thread_limit (cmd_parms *cmd, void *dummy, const char *arg) { int tmp_thread_limit; const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } tmp_thread_limit = at
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -