You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Justin Erenkrantz <je...@ebuilt.com> on 2001/07/14 22:54:50 UTC
[PATCH] Add intraprocess mutex to threaded MPM WAS Re: Terminiting threads in a process RE: [PATCH] Problems with MPM threaded
> > Ah. Yes, that makes more sense. But, that's not what's there now.
> >
> > Shall I submit a patch to threaded MPM to do this? -- justin
>
> Please.
This also includes my POD patch. I can separate it out if you don't
want the POD code merged yet. -- justin
Index: threaded.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/mpm/threaded/threaded.c,v
retrieving revision 1.44
diff -u -r1.44 threaded.c
--- threaded.c 2001/07/03 13:58:10 1.44
+++ threaded.c 2001/07/14 20:48:04
@@ -143,10 +143,7 @@
char ap_coredump_dir[MAX_STRING_LEN];
-static apr_file_t *pipe_of_death_in = NULL;
-static apr_file_t *pipe_of_death_out = NULL;
-static apr_lock_t *pipe_of_death_mutex; /* insures that a child process only
- consumes one character */
+static ap_pod_t *pipe_of_death;
/* *Non*-shared http_main globals... */
@@ -178,7 +175,13 @@
static int worker_thread_count;
static apr_lock_t *worker_thread_count_mutex;
-/* Locks for accept serialization */
+/* Locks for accept serialization
+ * worker_accept_mutex ensures that only one thread in a child process
+ * may be in accept. It also ensures that when we have
+ * workers_may_exit=1 that we exit.
+ * accept_mutex is the cross-process mutex which all children have.
+ */
+static apr_lock_t *worker_accept_mutex;
static apr_lock_t *accept_mutex;
static apr_lockmech_e_np accept_lock_mech = APR_LOCK_DEFAULT;
static const char *lock_fname;
@@ -494,29 +497,6 @@
}
}
-/* 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;
@@ -539,8 +519,8 @@
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_setup(&pollset, num_listensocks, 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
@@ -553,7 +533,10 @@
(void) ap_update_child_status(process_slot, thread_slot, SERVER_READY,
(request_rec *) NULL);
- if ((rv = SAFE_ACCEPT(apr_lock_acquire(accept_mutex)))
+
+ apr_lock_acquire(worker_accept_mutex);
+ if (!workers_may_exit &&
+ (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 "
@@ -580,12 +563,8 @@
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 (!ap_mpm_pod_check(pipe_of_death)) {
+ workers_may_exit = 1;
}
if (num_listensocks == 1) {
@@ -624,6 +603,12 @@
"process gracefully.");
workers_may_exit = 1;
}
+ if ((rv = apr_lock_release(worker_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--;
@@ -637,6 +622,12 @@
"process gracefully.");
workers_may_exit = 1;
}
+ if ((rv = apr_lock_release(worker_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);
@@ -780,12 +771,8 @@
}
/* 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 = apr_pcalloc(pchild, sizeof(*listensocks) * num_listensocks);
+ for (lr = ap_listeners, i = 0; i < num_listensocks; lr = lr->next, ++i)
listensocks[i]=lr->sd;
/* Setup worker threads */
@@ -799,9 +786,8 @@
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,
+ apr_lock_create(&worker_accept_mutex, APR_MUTEX, APR_INTRAPROCESS,
NULL, pchild);
-
ts = apr_palloc(pchild, sizeof(*ts));
apr_threadattr_create(&thread_attr, pchild);
@@ -894,29 +880,6 @@
return 0;
}
-/* If there aren't many connections coming in from the network, the child
- * processes may need to be awakened from their network i/o waits.
- * The pipe of death is an effective prod.
- */
-
-static void wake_up_and_die(void)
-{
- int i;
- char char_of_death = '!';
- apr_size_t one = 1;
- apr_status_t rv;
-
- for (i = 0; i < ap_daemons_limit;) {
- if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one))
- != APR_SUCCESS) {
- if (APR_STATUS_IS_EINTR(rv)) continue;
- ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
- "write pipe_of_death");
- }
- i++;
- }
-}
-
/* start up a bunch of children */
static void startup_children(int number_to_start)
{
@@ -955,8 +918,6 @@
int free_slots[MAX_SPAWN_RATE];
int last_non_dead;
int total_non_dead;
- apr_size_t one = 1;
- apr_status_t rv;
/* initialize the free_list */
free_length = 0;
@@ -1004,11 +965,7 @@
ap_max_daemons_limit = last_non_dead + 1;
if (idle_thread_count > max_spare_threads) {
- char char_of_death = '!';
- /* Kill off one child */
- if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, "write pipe_of_death");
- }
+ ap_mpm_pod_signal(pipe_of_death);
idle_spawn_rate = 1;
}
else if (idle_thread_count < min_spare_threads) {
@@ -1129,18 +1086,11 @@
pconf = _pconf;
ap_server_conf = s;
- rv = apr_file_pipe_create(&pipe_of_death_in, &pipe_of_death_out, pconf);
+ rv = ap_mpm_pod_open(pconf, &pipe_of_death);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv,
- (const server_rec*) ap_server_conf,
- "apr_file_pipe_create (pipe_of_death)");
- exit(1);
- }
-
- if ((rv = apr_file_pipe_timeout_set(pipe_of_death_in, 0)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv,
(const server_rec*) ap_server_conf,
- "apr_file_pipe_timeout_set (pipe_of_death)");
+ "ap_mpm_pod_open");
exit(1);
}
@@ -1208,7 +1158,7 @@
/* Time to gracefully shut down:
* Kill child processes, tell them to call child_exit, etc...
*/
- wake_up_and_die();
+ ap_mpm_pod_killpg(pipe_of_death, ap_daemons_limit);
if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM");
@@ -1249,7 +1199,7 @@
update_scoreboard_global();
/* wake up the children...time to die. But we'll have more soon */
- wake_up_and_die();
+ ap_mpm_pod_killpg(pipe_of_death, ap_daemons_limit);
if (is_graceful) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
Index: mpm.h
===================================================================
RCS file: /home/cvs/httpd-2.0/server/mpm/threaded/mpm.h,v
retrieving revision 1.5
diff -u -r1.5 mpm.h
--- mpm.h 2001/05/07 18:41:48 1.5
+++ mpm.h 2001/07/14 20:48:04
@@ -66,6 +66,7 @@
#define MPM_NAME "Threaded"
#define AP_MPM_NEEDS_RECLAIM_CHILD_PROCESSES 1
+#define AP_MPM_USES_POD 1
#define MPM_SYNC_CHILD_TABLE() (ap_sync_scoreboard_image())
#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)