📄 threaded.c
字号:
#else if (!one_process) { apr_signal(SIGSEGV, sig_coredump);#ifdef SIGBUS apr_signal(SIGBUS, sig_coredump);#endif /* SIGBUS */#ifdef SIGABORT apr_signal(SIGABORT, sig_coredump);#endif /* SIGABORT */#ifdef SIGABRT apr_signal(SIGABRT, sig_coredump);#endif /* SIGABRT */#ifdef SIGILL apr_signal(SIGILL, sig_coredump);#endif /* SIGILL */#ifdef SIGXCPU apr_signal(SIGXCPU, SIG_DFL);#endif /* SIGXCPU */#ifdef SIGXFSZ apr_signal(SIGXFSZ, SIG_DFL);#endif /* SIGXFSZ */ } apr_signal(SIGTERM, sig_term);#ifdef SIGHUP apr_signal(SIGHUP, restart);#endif /* SIGHUP */#ifdef SIGWINCH apr_signal(SIGWINCH, restart);#endif /* SIGWINCH */#ifdef SIGPIPE apr_signal(SIGPIPE, SIG_IGN);#endif /* SIGPIPE */#endif}/***************************************************************** * Here follows a long bunch of generic server bookkeeping stuff... */int ap_graceful_stop_signalled(void){ /* XXX - Does this really work? - Manoj */ return is_graceful;}/***************************************************************** * Child process main loop. */static void process_socket(apr_pool_t *p, apr_socket_t *sock, int my_child_num, int my_thread_num){ conn_rec *current_conn; long conn_id = AP_ID_FROM_CHILD_THREAD(my_child_num, my_thread_num); int csd; (void) apr_os_sock_get(&csd, sock); if (csd >= FD_SETSIZE) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL, "new file descriptor %d is too large; you probably need " "to rebuild Apache with a larger FD_SETSIZE " "(currently %d)", csd, FD_SETSIZE); apr_socket_close(sock); return; } ap_sock_disable_nagle(sock); current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id); if (current_conn) { ap_process_connection(current_conn); ap_lingering_close(current_conn); }}/* Sets workers_may_exit if we received a character on the pipe_of_death */static void check_pipe_of_death(void){ apr_lock_acquire(pipe_of_death_mutex); if (!workers_may_exit) { apr_status_t ret; char pipe_read_char; apr_size_t n = 1; ret = apr_recv(listensocks[0], &pipe_read_char, &n); if (APR_STATUS_IS_EAGAIN(ret)) { /* It lost the lottery. It must continue to suffer * through a life of servitude. */ } else { /* It won the lottery (or something else is very * wrong). Embrace death with open arms. */ workers_may_exit = 1; } } apr_lock_release(pipe_of_death_mutex);}static void * worker_thread(void * dummy){ proc_info * ti = dummy; int process_slot = ti->pid; int thread_slot = ti->tid; apr_pool_t *tpool = ti->tpool; apr_socket_t *csd = NULL; apr_pool_t *ptrans; /* Pool for per-transaction stuff */ apr_socket_t *sd = NULL; int n; int curr_pollfd, last_pollfd = 0; apr_pollfd_t *pollset; apr_status_t rv; free(ti); apr_pool_create(&ptrans, tpool); apr_lock_acquire(worker_thread_count_mutex); worker_thread_count++; apr_lock_release(worker_thread_count_mutex); apr_poll_setup(&pollset, num_listensocks+1, tpool); for(n=0 ; n <= num_listensocks ; ++n) apr_poll_socket_add(pollset, listensocks[n], APR_POLLIN); /* TODO: Switch to a system where threads reuse the results from earlier poll calls - manoj */ while (1) { workers_may_exit |= (ap_max_requests_per_child != 0) && (requests_this_child <= 0); if (workers_may_exit) break; (void) ap_update_child_status(process_slot, thread_slot, SERVER_READY, (request_rec *) NULL); if ((rv = SAFE_ACCEPT(apr_lock_acquire(accept_mutex))) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, "apr_lock_acquire failed. Attempting to shutdown " "process gracefully."); workers_may_exit = 1; } while (!workers_may_exit) { apr_status_t ret; apr_int16_t event; ret = apr_poll(pollset, &n, -1); if (ret != APR_SUCCESS) { if (APR_STATUS_IS_EINTR(ret)) { continue; } /* apr_poll() will only return errors in catastrophic * circumstances. Let's try exiting gracefully, for now. */ ap_log_error(APLOG_MARK, APLOG_ERR, ret, (const server_rec *) ap_server_conf, "apr_poll: (listen)"); workers_may_exit = 1; } if (workers_may_exit) break; apr_poll_revents_get(&event, listensocks[0], pollset); if (event & APR_POLLIN) { /* A process got a signal on the shutdown pipe. Check if we're * the lucky process to die. */ check_pipe_of_death(); continue; } if (num_listensocks == 1) { sd = ap_listeners->sd; goto got_fd; } else { /* find a listener */ curr_pollfd = last_pollfd; do { curr_pollfd++; if (curr_pollfd > num_listensocks) { curr_pollfd = 1; } /* XXX: Should we check for POLLERR? */ apr_poll_revents_get(&event, listensocks[curr_pollfd], pollset); if (event & APR_POLLIN) { last_pollfd = curr_pollfd; sd=listensocks[curr_pollfd]; goto got_fd; } } while (curr_pollfd != last_pollfd); } } got_fd: if (!workers_may_exit) { if ((rv = apr_accept(&csd, sd, ptrans)) != APR_SUCCESS) { csd = NULL; ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "apr_accept"); } if ((rv = SAFE_ACCEPT(apr_lock_release(accept_mutex))) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, "apr_lock_release failed. Attempting to shutdown " "process gracefully."); workers_may_exit = 1; } if (csd != NULL) { process_socket(ptrans, csd, process_slot, thread_slot); requests_this_child--; } } else { if ((rv = SAFE_ACCEPT(apr_lock_release(accept_mutex))) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, "apr_lock_release failed. Attempting to shutdown " "process gracefully."); workers_may_exit = 1; } break; } apr_pool_clear(ptrans); } apr_pool_destroy(tpool); ap_update_child_status(process_slot, thread_slot, SERVER_DEAD, (request_rec *) NULL); apr_lock_acquire(worker_thread_count_mutex); worker_thread_count--; if (worker_thread_count == 0) { /* All the threads have exited, now finish the shutdown process * by signalling the sigwait thread */ kill(ap_my_pid, SIGTERM); } apr_lock_release(worker_thread_count_mutex); return NULL;}static int check_signal(int signum){ switch (signum) { case SIGTERM: case SIGINT: just_die(signum); return 1; } return 0;}static void child_main(int child_num_arg){ apr_thread_t *thread; apr_threadattr_t *thread_attr; int i; int my_child_num = child_num_arg; proc_info *my_info = NULL; ap_listen_rec *lr; apr_status_t rv; ap_my_pid = getpid(); apr_pool_create(&pchild, pconf); /*stuff to do before we switch id's, so we have permissions.*/ reopen_scoreboard(pchild); rv = SAFE_ACCEPT(apr_lock_child_init(&accept_mutex, lock_fname, pchild)); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, "Couldn't initialize cross-process lock in child"); clean_child_exit(APEXIT_CHILDFATAL); } if (unixd_setup_child()) { clean_child_exit(APEXIT_CHILDFATAL); } ap_run_child_init(pchild, ap_server_conf); /*done with init critical section */ rv = apr_setup_signal_thread(); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, "Couldn't initialize signal thread"); clean_child_exit(APEXIT_CHILDFATAL); } requests_this_child = ap_max_requests_per_child; /* Set up the pollfd array */ listensocks = apr_pcalloc(pchild, sizeof(*listensocks) * (num_listensocks + 1));#if APR_FILES_AS_SOCKETS apr_socket_from_file(&listensocks[0], pipe_of_death_in);#endif for (lr = ap_listeners, i = 1; i <= num_listensocks; lr = lr->next, ++i) listensocks[i]=lr->sd; /* Setup worker threads */ worker_thread_count = 0; apr_lock_create(&worker_thread_count_mutex, APR_MUTEX, APR_INTRAPROCESS, NULL, pchild); apr_lock_create(&pipe_of_death_mutex, APR_MUTEX, APR_INTRAPROCESS, NULL, pchild); apr_threadattr_create(&thread_attr, pchild); apr_threadattr_detach_set(thread_attr); rv = apr_create_signal_thread(&thread, thread_attr, check_signal, pchild); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, "Couldn't create signal thread"); clean_child_exit(APEXIT_CHILDFATAL); } for (i=0; i < ap_threads_per_child - 1; i++) { my_info = (proc_info *)malloc(sizeof(proc_info)); if (my_info == NULL) { ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf, "malloc: out of memory"); clean_child_exit(APEXIT_CHILDFATAL); } my_info->pid = my_child_num; my_info->tid = i; my_info->sd = 0; apr_pool_create(&my_info->tpool, pchild); /* We are creating threads right now */ (void) ap_update_child_status(my_child_num, i, SERVER_STARTING, (request_rec *) NULL); if ((rv = apr_thread_create(&thread, thread_attr, worker_thread, my_info, pchild))) { ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, "apr_thread_create: unable to create worker thread"); /* In case system resources are maxxed out, we don't want Apache running away with the CPU trying to fork over and over and over again if we exit. */ sleep(10); clean_child_exit(APEXIT_CHILDFATAL); } /* We let each thread update it's own scoreboard entry. This is done * because it let's us deal with tid better. */ } my_info = (proc_info *)malloc(sizeof(proc_info)); if (my_info == NULL) { ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf, "malloc: out of memory"); clean_child_exit(APEXIT_CHILDFATAL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -