You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ma...@hyperreal.org on 1999/07/09 22:40:27 UTC
cvs commit: apache-2.0/mpm/src/modules/mpm/mpmt_pthread Makefile.tmpl acceptlock.c mpmt_pthread.c mpmt_pthread.h scoreboard.c http_accept.c
manoj 99/07/09 13:40:27
Modified: mpm/src/include scoreboard.h
mpm/src/modules/mpm/mpmt_pthread Makefile.tmpl acceptlock.c
mpmt_pthread.c mpmt_pthread.h scoreboard.c
Removed: mpm/src/include http_accept.h
mpm/src/modules/mpm/mpmt_pthread http_accept.c
Log:
Get rid of the accept abstraction, which seems out-of-place in the MPM
codebase, and make the poll-accept model the only model supported. Also,
some code was cleaned up and rewritten in the process.
Revision Changes Path
1.3 +0 -1 apache-2.0/mpm/src/include/scoreboard.h
Index: scoreboard.h
===================================================================
RCS file: /home/cvs/apache-2.0/mpm/src/include/scoreboard.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -u -r1.2 -r1.3
--- scoreboard.h 1999/07/09 20:30:13 1.2
+++ scoreboard.h 1999/07/09 20:40:09 1.3
@@ -174,7 +174,6 @@
pid_t pid;
ap_generation_t generation; /* generation of this child */
int worker_threads;
- int acceptor_threads;
#ifdef OPTIMIZE_TIMEOUTS
time_t last_rtime; /* time(0) of the last change */
vtime_t last_vtime; /* the last vtime the parent has seen */
1.4 +15 -26 apache-2.0/mpm/src/modules/mpm/mpmt_pthread/Makefile.tmpl
Index: Makefile.tmpl
===================================================================
RCS file: /home/cvs/apache-2.0/mpm/src/modules/mpm/mpmt_pthread/Makefile.tmpl,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -u -r1.3 -r1.4
--- Makefile.tmpl 1999/07/07 15:11:05 1.3
+++ Makefile.tmpl 1999/07/09 20:40:19 1.4
@@ -2,9 +2,9 @@
LIB=libmpmt_pthread.$(LIBEXT)
OBJS=\
- mpmt_pthread.o acceptlock.o http_accept.o scoreboard.o
+ mpmt_pthread.o acceptlock.o scoreboard.o
OBJS_PIC=\
- mpmt_pthread.lo acceptlock.lo http_accept.lo scoreboard.lo
+ mpmt_pthread.lo acceptlock.lo scoreboard.lo
all: lib
@@ -64,22 +64,11 @@
$(INCDIR)/ap.h $(INCDIR)/apr.h \
$(INCDIR)/util_uri.h $(INCDIR)/http_main.h \
$(INCDIR)/http_log.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
- $(INCDIR)/http_conf_globals.h $(INCDIR)/http_core.h \
- $(INCDIR)/http_vhost.h $(INCDIR)/util_script.h \
- acceptlock.h $(INCDIR)/http_accept.h
-http_accept.o: http_accept.c $(INCDIR)/httpd.h \
- $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
- $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
- $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
- $(INCDIR)/hsregex.h $(INCDIR)/alloc.h \
- $(INCDIR)/buff.h $(INCDIR)/ap_iol.h \
- $(INCDIR)/ap.h $(INCDIR)/apr.h \
- $(INCDIR)/util_uri.h $(INCDIR)/http_log.h \
- $(INCDIR)/http_main.h $(INCDIR)/http_conf_globals.h \
- acceptlock.h $(INCDIR)/scoreboard.h \
- $(INCDIR)/http_config.h $(INCDIR)/ap_listen.h \
- $(INCDIR)/http_accept.h mpmt_pthread.h
+ $(INCDIR)/ap_hooks.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/http_request.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_vhost.h \
+ $(INCDIR)/util_script.h acceptlock.h mpmt_pthread.h \
+ $(OSDIR)/unixd.h
mpmt_pthread.o: mpmt_pthread.c $(INCDIR)/httpd.h \
$(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
@@ -89,11 +78,11 @@
$(INCDIR)/ap.h $(INCDIR)/apr.h \
$(INCDIR)/util_uri.h $(INCDIR)/http_main.h \
$(INCDIR)/http_log.h $(INCDIR)/http_config.h \
- $(INCDIR)/http_core.h $(INCDIR)/http_connection.h \
- $(INCDIR)/ap_mpm.h $(OSDIR)/unixd.h \
- $(OSDIR)/iol_socket.h $(INCDIR)/ap_listen.h \
- $(INCDIR)/scoreboard.h acceptlock.h \
- $(INCDIR)/http_accept.h
+ $(INCDIR)/ap_hooks.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_connection.h $(INCDIR)/ap_mpm.h \
+ $(OSDIR)/unixd.h $(OSDIR)/iol_socket.h \
+ $(INCDIR)/ap_listen.h $(INCDIR)/scoreboard.h \
+ acceptlock.h ../../../lib/expat-lite/xmlparse.h
scoreboard.o: scoreboard.c $(INCDIR)/httpd.h \
$(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
$(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
@@ -103,6 +92,6 @@
$(INCDIR)/ap.h $(INCDIR)/apr.h \
$(INCDIR)/util_uri.h $(INCDIR)/http_log.h \
$(INCDIR)/http_main.h $(INCDIR)/http_core.h \
- $(INCDIR)/http_config.h $(OSDIR)/unixd.h \
- $(INCDIR)/http_conf_globals.h mpmt_pthread.h \
- $(INCDIR)/scoreboard.h
+ $(INCDIR)/http_config.h $(INCDIR)/ap_hooks.h \
+ $(OSDIR)/unixd.h $(INCDIR)/http_conf_globals.h \
+ mpmt_pthread.h $(INCDIR)/scoreboard.h
1.5 +2 -2 apache-2.0/mpm/src/modules/mpm/mpmt_pthread/acceptlock.c
Index: acceptlock.c
===================================================================
RCS file: /home/cvs/apache-2.0/mpm/src/modules/mpm/mpmt_pthread/acceptlock.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -u -r1.4 -r1.5
--- acceptlock.c 1999/07/09 20:30:15 1.4
+++ acceptlock.c 1999/07/09 20:40:20 1.5
@@ -67,8 +67,8 @@
#include "util_script.h" /* to force util_script.c linking */
#include "util_uri.h"
#include "acceptlock.h"
+#include "mpmt_pthread.h" /* For clean_child_exit */
#include "unixd.h"
-#include "http_accept.h"
#include <netinet/tcp.h>
#include <stdio.h>
@@ -78,7 +78,7 @@
#include <sys/shm.h>
#endif
-#include <pthread.h>
+#include <pthread.h>
/* TODO: all these calls have to be ap_ prefixed, right? */
/* Number of cross-process locks we're managing */
1.6 +150 -35 apache-2.0/mpm/src/modules/mpm/mpmt_pthread/mpmt_pthread.c
Index: mpmt_pthread.c
===================================================================
RCS file: /home/cvs/apache-2.0/mpm/src/modules/mpm/mpmt_pthread/mpmt_pthread.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -u -r1.5 -r1.6
--- mpmt_pthread.c 1999/07/09 20:30:15 1.5
+++ mpmt_pthread.c 1999/07/09 20:40:22 1.6
@@ -70,16 +70,15 @@
#include "scoreboard.h"
#include "acceptlock.h"
-#include "http_accept.h"
+#include <poll.h>
#include <netinet/tcp.h>
-#include <pthread.h>
+#include <pthread.h>
/*
* Actual definitions of config globals
*/
int ap_threads_per_child=0; /* Worker threads per child */
-int ap_acceptors_per_child=0; /* Accept threads per child */
int ap_max_requests_per_child=0;
static char *ap_pid_fname=NULL;
static char *ap_scoreboard_fname=NULL;
@@ -89,7 +88,25 @@
static int ap_daemons_limit=0;
static time_t ap_restart_time=0;
API_VAR_EXPORT int ap_extended_status = 0;
+static int workers_may_exit = 0;
+static int requests_this_child;
+static int num_listenfds = 0;
+static struct pollfd *listenfds_child; /* The listenfds that each thread copies
+ for itself */
+
+/* The structure used to pass unique initialization info to each thread */
+typedef struct {
+ int pid;
+ int tid;
+ int sd;
+ pool *tpool; /* "pthread" would be confusing */
+} proc_info;
+#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next != NULL) {stmt;}} while (0)
+#else
+#define SAFE_ACCEPT(stmt) do {stmt;} while (0)
+#endif
/*
* The max child slot ever assigned, preserved across restarts. Necessary
@@ -100,7 +117,8 @@
static char ap_coredump_dir[MAX_STRING_LEN];
-int ap_pipe_of_death[2];
+static int pipe_of_death[2];
+static pthread_mutex_t pipe_of_death_mutex;
/* *Non*-shared http_main globals... */
@@ -841,8 +859,15 @@
int thread_slot = ti->tid;
pool *tpool = ti->tpool;
struct sockaddr sa_client;
- int csd;
+ int csd = -1;
pool *ptrans; /* Pool for per-transaction stuff */
+ int sd = -1;
+ int srv;
+ int ret;
+ char pipe_read_char;
+ int curr_pollfd, last_pollfd = 0;
+ size_t len = sizeof(struct sockaddr);
+ struct pollfd *listenfds;
free(ti);
@@ -852,15 +877,91 @@
worker_thread_count++;
pthread_mutex_unlock(&worker_thread_count_mutex);
- while (1) {
+ /* TODO: Switch to a system where threads reuse the results from earlier
+ poll calls - manoj */
+ /* set up each thread's individual pollfd array */
+ listenfds = ap_palloc(tpool, sizeof(struct pollfd) * (num_listenfds + 1));
+ memcpy(listenfds, listenfds_child, sizeof(struct pollfd) * (num_listenfds + 1));
+ while (!workers_may_exit) {
+ 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);
- csd = get_connection(&sa_client);
- if (csd < 0) {
+ (request_rec *) NULL);
+ SAFE_ACCEPT(intra_mutex_on(0));
+ if (workers_may_exit) {
+ SAFE_ACCEPT(intra_mutex_off(0));
break;
- }
+ }
+ SAFE_ACCEPT(accept_mutex_on(0));
+ while (!workers_may_exit) {
+ srv = poll(listenfds, num_listenfds + 1, -1);
+ if (srv < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ /* poll() will only return errors in catastrophic
+ * circumstances. Let's try exiting gracefully, for now. */
+ ap_log_error(APLOG_MARK, APLOG_ERR, (const server_rec *)
+ ap_get_server_conf(), "poll: (listen)");
+ workers_may_exit = 1;
+ }
+
+ if (workers_may_exit) break;
+
+ if (listenfds[0].revents & POLLIN) {
+ /* A process got a signal on the shutdown pipe. Check if we're
+ * the lucky process to die. */
+ pthread_mutex_lock(&pipe_of_death_mutex);
+ if (!workers_may_exit) {
+ ret = read(listenfds[0].fd, &pipe_read_char, 1);
+ if (ret == -1 && errno == EAGAIN) {
+ /* It lost the lottery. It must continue to suffer
+ * through a life of servitude. */
+ pthread_mutex_unlock(&pipe_of_death_mutex);
+ continue;
+ }
+ else {
+ /* It won the lottery (or something else is very
+ * wrong). Embrace death with open arms. */
+ workers_may_exit = 1;
+ pthread_mutex_unlock(&pipe_of_death_mutex);
+ break;
+ }
+ }
+ pthread_mutex_unlock(&pipe_of_death_mutex);
+ }
+
+ if (num_listenfds == 1) {
+ sd = ap_listeners->fd;
+ goto got_fd;
+ }
+ else {
+ /* find a listener */
+ curr_pollfd = last_pollfd;
+ do {
+ curr_pollfd++;
+ if (curr_pollfd > num_listenfds) {
+ curr_pollfd = 1;
+ }
+ /* XXX: Should we check for POLLERR? */
+ if (listenfds[curr_pollfd].revents & POLLIN) {
+ last_pollfd = curr_pollfd;
+ sd = listenfds[curr_pollfd].fd;
+ goto got_fd;
+ }
+ } while (curr_pollfd != last_pollfd);
+ }
+ }
+ got_fd:
+ SAFE_ACCEPT(accept_mutex_off(0));
+ SAFE_ACCEPT(intra_mutex_off(0));
+ if (workers_may_exit) break;
+ csd = ap_accept(sd, &sa_client, &len);
process_socket(ptrans, &sa_client, csd, process_slot, thread_slot);
- ap_clear_pool(ptrans);
+ ap_clear_pool(ptrans);
+ requests_this_child--;
}
ap_destroy_pool(tpool);
@@ -888,6 +989,7 @@
int i;
int my_child_num = child_num_arg;
proc_info *my_info = NULL;
+ ap_listen_rec *lr;
my_pid = getpid();
pchild = ap_make_sub_pool(pconf);
@@ -899,7 +1001,8 @@
clean_child_exit(APEXIT_CHILDFATAL);
}
- accept_child_init(pchild, ap_threads_per_child);
+ SAFE_ACCEPT(intra_mutex_init(pchild, 1));
+ SAFE_ACCEPT(accept_mutex_child_init(pchild));
ap_child_init_hook(pchild, server_conf);
/*done with init critical section */
@@ -911,10 +1014,24 @@
ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf, "pthread_sigmask");
}
+ requests_this_child = ap_max_requests_per_child;
+
+ /* Set up the pollfd array */
+ listenfds_child = ap_palloc(pchild, sizeof(struct pollfd) * (num_listenfds + 1));
+ listenfds_child[0].fd = pipe_of_death[0];
+ listenfds_child[0].events = POLLIN;
+ listenfds_child[0].revents = 0;
+ for (lr = ap_listeners, i = 1; i <= num_listenfds; lr = lr->next, ++i) {
+ listenfds_child[i].fd = lr->fd;
+ listenfds_child[i].events = POLLIN; /* should we add POLLPRI ?*/
+ listenfds_child[i].revents = 0;
+ }
+
/* Setup worker threads */
worker_thread_count = 0;
pthread_mutex_init(&worker_thread_count_mutex, NULL);
+ pthread_mutex_init(&pipe_of_death_mutex, NULL);
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
for (i=0; i < ap_threads_per_child; i++) {
@@ -949,7 +1066,6 @@
}
pthread_attr_destroy(&thread_attr);
- start_accepting_connections(my_child_num);
/* This thread will be the one responsible for handling signals */
sigemptyset(&sig_mask);
@@ -972,13 +1088,6 @@
{
int pid;
- if (ap_acceptors_per_child + ap_threads_per_child > HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_ERR, s,
- "Worker threads plus acceptor threads is greater than HARD_THREAD_LIMIT, please correct");
- exit(-1);
- }
-
-
if (slot + 1 > max_daemons_limit) {
max_daemons_limit = slot + 1;
}
@@ -1128,8 +1237,8 @@
if (idle_count_ceil > ap_daemons_max_free) {
/* Kill off one child */
char char_of_death = '!';
- if (write(ap_pipe_of_death[1], &char_of_death, 1) == -1) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "write ap_pipe_of_death");
+ if (write(pipe_of_death[1], &char_of_death, 1) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "write pipe_of_death");
}
idle_spawn_rate = 1;
}
@@ -1190,7 +1299,7 @@
if (pid >= 0) {
child_slot = find_child_by_pid(pid);
if (child_slot >= 0) {
- for (i = 0; i < ap_threads_per_child + ap_acceptors_per_child; i++)
+ for (i = 0; i < ap_threads_per_child; i++)
ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
if (remaining_children_to_start
@@ -1244,26 +1353,25 @@
int ap_mpm_run(pool *_pconf, pool *plog, server_rec *s)
{
int remaining_children_to_start;
- int listener_count;
pconf = _pconf;
server_conf = s;
- if (pipe(ap_pipe_of_death) == -1) {
+ if (pipe(pipe_of_death) == -1) {
ap_log_error(APLOG_MARK, APLOG_ERR,
(const server_rec*) server_conf,
"pipe: (pipe_of_death)");
exit(1);
}
- ap_note_cleanups_for_fd(pconf, ap_pipe_of_death[0]);
- ap_note_cleanups_for_fd(pconf, ap_pipe_of_death[1]);
- if (fcntl(ap_pipe_of_death[0], F_SETFD, O_NONBLOCK) == -1) {
+ ap_note_cleanups_for_fd(pconf, pipe_of_death[0]);
+ ap_note_cleanups_for_fd(pconf, pipe_of_death[1]);
+ if (fcntl(pipe_of_death[0], F_SETFD, O_NONBLOCK) == -1) {
ap_log_error(APLOG_MARK, APLOG_ERR,
(const server_rec*) server_conf,
"fcntl: O_NONBLOCKing (pipe_of_death)");
exit(1);
}
server_conf = s;
- if ((listener_count = setup_listeners(pconf, server_conf)) < 1) {
+ if ((num_listenfds = setup_listeners(pconf, server_conf)) < 1) {
/* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s,
"no listening sockets available, shutting down");
@@ -1272,7 +1380,7 @@
ap_clear_pool(plog);
ap_open_logs(server_conf, plog);
ap_log_pid(pconf, ap_pid_fname);
- accept_parent_init(pconf, listener_count);
+ SAFE_ACCEPT(accept_mutex_init(pconf, 1));
if (!is_graceful) {
reinit_scoreboard(pconf);
}
@@ -1365,8 +1473,8 @@
/* kill off the idle ones */
for (i = 0; i < ap_daemons_limit; ++i) {
- if (write(ap_pipe_of_death[1], &char_of_death, 1) == -1) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "write ap_pipe_of_death");
+ if (write(pipe_of_death[1], &char_of_death, 1) == -1) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "write pipe_of_death");
}
}
@@ -1375,8 +1483,7 @@
*/
for (i = 0; i < ap_daemons_limit; ++i) {
- for (j = 0; j < ap_threads_per_child + ap_acceptors_per_child;
- j++) {
+ for (j = 0; j < ap_threads_per_child; j++) {
if (ap_scoreboard_image->servers[i][j].status != SERVER_DEAD) {
ap_scoreboard_image->servers[i][j].status = SERVER_GRACEFUL;
}
@@ -1548,7 +1655,15 @@
}
ap_threads_per_child = atoi(arg);
- if (ap_threads_per_child < 1) {
+ if (ap_threads_per_child > HARD_THREAD_LIMIT) {
+ fprintf(stderr, "WARNING: ThreadsPerChild of %d exceeds compile time"
+ "limit of %d threads,\n", ap_threads_per_child,
+ HARD_THREAD_LIMIT);
+ fprintf(stderr, " lowering ThreadsPerChild to %d. To increase, please"
+ "see the\n", HARD_THREAD_LIMIT);
+ fprintf(stderr, " HARD_THREAD_LIMIT define in src/include/httpd.h.\n");
+ }
+ else if (ap_threads_per_child < 1) {
fprintf(stderr, "WARNING: Require ThreadsPerChild > 0, setting to 1\n");
ap_threads_per_child = 1;
}
1.2 +1 -1 apache-2.0/mpm/src/modules/mpm/mpmt_pthread/mpmt_pthread.h
Index: mpmt_pthread.h
===================================================================
RCS file: /home/cvs/apache-2.0/mpm/src/modules/mpm/mpmt_pthread/mpmt_pthread.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -u -r1.1 -r1.2
--- mpmt_pthread.h 1999/06/27 03:45:15 1.1
+++ mpmt_pthread.h 1999/07/09 20:40:23 1.2
@@ -56,8 +56,8 @@
*/
extern int ap_threads_per_child;
-extern int ap_acceptors_per_child;
extern int ap_max_requests_per_child;
extern int ap_pipe_of_death[2];
extern void clean_child_exit(int);
extern int ap_extended_status;
+extern void clean_child_exit(int);
1.3 +0 -1 apache-2.0/mpm/src/modules/mpm/mpmt_pthread/scoreboard.c
Index: scoreboard.c
===================================================================
RCS file: /home/cvs/apache-2.0/mpm/src/modules/mpm/mpmt_pthread/scoreboard.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -u -r1.2 -r1.3
--- scoreboard.c 1999/06/27 03:45:15 1.2
+++ scoreboard.c 1999/07/09 20:40:23 1.3
@@ -590,7 +590,6 @@
&& old_status == SERVER_STARTING) {
ss->tid = pthread_self();
ps->worker_threads = ap_threads_per_child;
- ps->acceptor_threads = ap_acceptors_per_child;
}
if (ap_extended_status) {