Commit a2a7de2a authored by Brian Havard's avatar Brian Havard
Browse files

OS/2: Clean up spmt_os2 mpm to get shutdowns working cleanly.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84999 13f79535-47bb-0310-9956-ffa450edef68
parent a422633c
Loading
Loading
Loading
Loading
+66 −57
Original line number Diff line number Diff line
@@ -177,13 +177,11 @@ static void clean_child_exit(int code)



static HMTX lock_sem = -1;
static ap_lock_t *accept_mutex = NULL;

static ap_status_t accept_mutex_cleanup(void *foo)
static ap_status_t accept_mutex_child_cleanup(void *foo)
{
    DosReleaseMutexSem(lock_sem);
    DosCloseMutexSem(lock_sem);
    return APR_SUCCESS;
    return ap_unlock(accept_mutex);
}

/*
@@ -192,15 +190,7 @@ static ap_status_t accept_mutex_cleanup(void *foo)
 */
static void accept_mutex_child_init(ap_pool_t *p)
{
    int rc = DosOpenMutexSem(NULL, &lock_sem);

    if (rc != 0) {
	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, server_conf,
		    "Child cannot open lock semaphore, rc=%d", rc);
	clean_child_exit(APEXIT_CHILDINIT);
    } else {
        ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
    }
    ap_register_cleanup(p, NULL, accept_mutex_child_cleanup, ap_null_cleanup);
}

/*
@@ -209,35 +199,33 @@ static void accept_mutex_child_init(ap_pool_t *p)
 */
static void accept_mutex_init(ap_pool_t *p)
{
    int rc = DosCreateMutexSem(NULL, &lock_sem, DC_SEM_SHARED, FALSE);
    ap_status_t rc = ap_create_lock(&accept_mutex, APR_MUTEX, APR_INTRAPROCESS, NULL, p);

    if (rc != 0) {
	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, server_conf,
		    "Parent cannot create lock semaphore, rc=%d", rc);
	exit(APEXIT_INIT);
    if (rc != APR_SUCCESS) {
	ap_log_error(APLOG_MARK, APLOG_EMERG, rc, server_conf,
		    "Error creating accept lock. Exiting!");
	clean_child_exit(APEXIT_CHILDFATAL);
    }

    ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
}

static void accept_mutex_on(void)
{
    int rc = DosRequestMutexSem(lock_sem, SEM_INDEFINITE_WAIT);
    ap_status_t rc = ap_lock(accept_mutex);

    if (rc != 0) {
	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, server_conf,
		    "OS2SEM: Error %d getting accept lock. Exiting!", rc);
    if (rc != APR_SUCCESS) {
	ap_log_error(APLOG_MARK, APLOG_EMERG, rc, server_conf,
		    "Error getting accept lock. Exiting!");
	clean_child_exit(APEXIT_CHILDFATAL);
    }
}

static void accept_mutex_off(void)
{
    int rc = DosReleaseMutexSem(lock_sem);
    ap_status_t rc = ap_unlock(accept_mutex);

    if (rc != 0) {
	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, server_conf,
		    "OS2SEM: Error %d freeing accept lock. Exiting!", rc);
    if (rc != APR_SUCCESS) {
	ap_log_error(APLOG_MARK, APLOG_EMERG, rc, server_conf,
		    "Error freeing accept lock. Exiting!");
	clean_child_exit(APEXIT_CHILDFATAL);
    }
}
@@ -867,6 +855,8 @@ API_EXPORT(void) ap_child_terminate(request_rec *r)
    ap_scoreboard_image->parent[THREAD_GLOBAL(child_num)].deferred_die = 1;
}



int ap_graceful_stop_signalled(void)
{
    if (ap_scoreboard_image->parent[THREAD_GLOBAL(child_num)].deferred_die ||
@@ -878,6 +868,18 @@ int ap_graceful_stop_signalled(void)



int ap_stop_signalled(void)
{
    if (shutdown_pending || restart_pending ||
        ap_scoreboard_image->parent[THREAD_GLOBAL(child_num)].deferred_die ||
	ap_scoreboard_image->global.running_generation != ap_scoreboard_image->parent[THREAD_GLOBAL(child_num)].generation) {
	return 1;
    }
    return 0;
}



static int setup_listeners(ap_pool_t *pchild, ap_pollfd_t **listen_poll)
{
    ap_listen_rec *lr;
@@ -946,7 +948,7 @@ static void child_main(void *child_num_arg)
    signal(SIGHUP, just_die);
    signal(SIGTERM, just_die);

    while (!ap_graceful_stop_signalled()) {
    while (!ap_stop_signalled()) {
        BUFF *conn_io;
        int srv;
        ap_socket_t *sd;
@@ -979,12 +981,16 @@ static void child_main(void *child_num_arg)
	/* Lock around "accept", if necessary */
        SAFE_ACCEPT(accept_mutex_on());

        if (ap_stop_signalled()) {
            clean_child_exit(0);
        }

	for (;;) {
	    if (ap_listeners->next) {
		/* more than one socket */
                srv = ap_poll(listen_poll, &nsds, -1);

		if (srv < 0 && errno != EINTR) {
		if (srv != APR_SUCCESS) {
		    /* Single Unix documents select as returning errnos
		     * EBADF, EINTR, and EINVAL... and in none of those
		     * cases does it make sense to continue.  In fact
@@ -995,9 +1001,6 @@ static void child_main(void *child_num_arg)
		    clean_child_exit(1);
		}

		if (srv <= 0)
		    continue;

		/* we remember the last_lr we searched last time around so that
		   we don't end up starving any particular listening socket */
		if (first_lr == NULL) {
@@ -1036,15 +1039,7 @@ static void child_main(void *child_num_arg)
	     * defer the exit
	     */
            THREAD_GLOBAL(usr1_just_die) = 0;
	    for (;;) {
		if (ap_scoreboard_image->parent[THREAD_GLOBAL(child_num)].deferred_die) {
		    /* we didn't get a socket, and we were told to die */
		    clean_child_exit(0);
		}
            rv = ap_accept(&csd, sd, ptrans);
		if (rv != APR_EINTR)
		    break;
	    }

	    if (rv == APR_SUCCESS)
		break;		/* We have a socket ready for reading */
@@ -1060,7 +1055,7 @@ static void child_main(void *child_num_arg)
		 * lead to never-ending loops here.  So it seems best
		 * to just exit in most cases.
		 */
                switch (rv) {
                switch (ap_canonical_error(rv)) {
#ifdef EPROTO
		    /* EPROTO on certain older kernels really means
		     * ECONNABORTED, so we need to ignore it for them.
@@ -1101,6 +1096,12 @@ static void child_main(void *child_num_arg)
		case ENETUNREACH:
#endif
                    break;

                case EINTR:
                    /* We only get hit by an EINTR if the parent is
                     * killing us off
                     */
                    clean_child_exit(0);
		default:
		    ap_log_error(APLOG_MARK, APLOG_ERR, rv, server_conf,
				"accept: (client socket)");
@@ -1108,7 +1109,7 @@ static void child_main(void *child_num_arg)
		}
	    }

	    if (ap_graceful_stop_signalled()) {
	    if (ap_stop_signalled()) {
		clean_child_exit(0);
	    }
	    THREAD_GLOBAL(usr1_just_die) = 1;
@@ -1527,6 +1528,12 @@ int ap_mpm_run(ap_pool_t *_pconf, ap_pool_t *plog, server_rec *s)
        int slot;
        TID tid;
        ULONG rc;
        ap_listen_rec *lr;

        for (lr = ap_listeners; lr; lr = lr->next) {
            ap_close_socket(lr->sd);
            DosSleep(0);
        }

        /* Kill off running threads */
        for (slot=0; slot<max_daemons_limit; slot++) {
@@ -1534,6 +1541,7 @@ int ap_mpm_run(ap_pool_t *_pconf, ap_pool_t *plog, server_rec *s)
                tid = ap_scoreboard_image->parent[slot].tid;
                rc = DosKillThread(tid);

                if (rc != ERROR_INVALID_THREADID) { // Already dead, ignore
                    if (rc == 0) {
                        rc = DosWaitThread(&tid, DCWW_WAIT);

@@ -1547,6 +1555,7 @@ int ap_mpm_run(ap_pool_t *_pconf, ap_pool_t *plog, server_rec *s)
                    }
                }
            }
        }

        /* cleanup pid file on normal shutdown */
        pidfile = ap_server_root_relative (pconf, ap_pid_fname);