📄 spmt_os2.c
字号:
/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * Portions of this software are based upon public domain software * originally written at the National Center for Supercomputing Applications, * University of Illinois, Urbana-Champaign. */#define CORE_PRIVATE#define INCL_DOS#define INCL_DOSERRORS#include "ap_config.h"#include "httpd.h"#include "mpm_default.h"#include "http_main.h"#include "http_log.h"#include "http_config.h"#include "http_core.h" /* for get_remote_host */#include "http_connection.h"#include "mpm.h"#include "ap_mpm.h"#include "ap_listen.h"#include "apr_portable.h"#include "mpm_common.h"#include "apr_strings.h"#include <os2.h>#include <stdlib.h>#include <sys/signal.h>#include <process.h>#include <time.h>#include <io.h>/* config globals */static int ap_max_requests_per_child=0;static char *ap_pid_fname=NULL;static int ap_daemons_to_start=0;static int ap_daemons_min_free=0;static int ap_daemons_max_free=0;static int ap_daemons_limit=0;/* * The max child slot ever assigned, preserved across restarts. Necessary * to deal with MaxClients changes across SIGUSR1 restarts. We use this * value to optimize routines that have to scan the entire scoreboard. */static int max_daemons_limit = -1;int ap_threads_per_child = HARD_THREAD_LIMIT;ap_generation_t volatile ap_my_generation=0; /* Used by the scoreboard */char ap_coredump_dir[MAX_STRING_LEN];/* *Non*-shared http_main globals... */server_rec *ap_server_conf;/* one_process --- debugging mode variable; can be set from the command line * with the -X flag. If set, this gets you the child_main loop running * in the process which originally started up (no detach, no make_child), * which is a pretty nice debugging environment. (You'll get a SIGHUP * early in standalone_main; just continue through. This is the server * trying to kill off any child processes which it might have lying * around --- Apache doesn't keep track of their pids, it just sends * SIGHUP to the process group, ignoring it in the root process. * Continue through and you'll be fine.). */static int one_process = 0;static apr_pool_t *pconf; /* Pool for config stuff */struct thread_globals { int thread_num; apr_pool_t *pchild; /* Pool for httpd child stuff */ int usr1_just_die;};static struct thread_globals **ppthread_globals = NULL;#define THREAD_GLOBAL(gvar) ((*ppthread_globals)->gvar)struct thread_control_t { apr_wait_t thread_retval; char deferred_die; ap_generation_t generation; /* generation of this thread */} thread_control[HARD_THREAD_LIMIT];/* a clean exit from a child with proper cleanup */static void clean_child_exit(int code){ if (THREAD_GLOBAL(pchild)) { apr_pool_destroy(THREAD_GLOBAL(pchild)); } thread_control[THREAD_GLOBAL(thread_num)].deferred_die = 0; thread_control[THREAD_GLOBAL(thread_num)].thread_retval = code; _endthread();}static apr_lock_t *accept_mutex = NULL;static apr_status_t accept_mutex_child_cleanup(void *foo){ return apr_lock_release(accept_mutex);}/* * Initialize mutex lock. * Done by each child at it's birth */static void accept_mutex_child_init(apr_pool_t *p){ apr_pool_cleanup_register(p, NULL, accept_mutex_child_cleanup, apr_pool_cleanup_null);}/* * Initialize mutex lock. * Must be safe to call this on a restart. */static void accept_mutex_init(apr_pool_t *p){ apr_status_t rc = apr_lock_create(&accept_mutex, APR_MUTEX, APR_INTRAPROCESS, NULL, p); if (rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_EMERG, rc, ap_server_conf, "Error creating accept lock. Exiting!"); clean_child_exit(APEXIT_CHILDFATAL); }}static void accept_mutex_on(void){ apr_status_t rc = apr_lock_acquire(accept_mutex); if (rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_EMERG, rc, ap_server_conf, "Error getting accept lock. Exiting!"); clean_child_exit(APEXIT_CHILDFATAL); }}static void accept_mutex_off(void){ apr_status_t rc = apr_lock_release(accept_mutex); if (rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_EMERG, rc, ap_server_conf, "Error freeing accept lock. Exiting!"); clean_child_exit(APEXIT_CHILDFATAL); }}/* On some architectures it's safe to do unserialized accept()s in the single * Listen case. But it's never safe to do it in the case where there's * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT * when it's safe in the single Listen case. */#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)#else#define SAFE_ACCEPT(stmt) do {stmt;} while(0)#endifstatic int find_thread_by_tid(int tid){ int i; for (i = 0; i < max_daemons_limit; ++i) if (ap_scoreboard_image->servers[0][i].tid == tid) return i; return -1;}/* Finally, this routine is used by the caretaker thread to wait for * a while... *//* number of calls to wait_or_timeout between writable probes */#ifndef INTERVAL_OF_WRITABLE_PROBES#define INTERVAL_OF_WRITABLE_PROBES 10#endifstatic int wait_or_timeout_counter;static int wait_or_timeout(apr_wait_t *status){ int ret; ULONG tid; ++wait_or_timeout_counter; if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) { wait_or_timeout_counter = 0;#if APR_HAS_OTHER_CHILD apr_proc_probe_writable_fds();#endif } tid = 0; ret = DosWaitThread(&tid, DCWW_NOWAIT); if (ret == 0) { int thread_num = find_thread_by_tid(tid); ap_assert( thread_num > 0 ); *status = thread_control[thread_num].thread_retval; return tid; } DosSleep(SCOREBOARD_MAINTENANCE_INTERVAL / 1000); return -1;}/* handle all varieties of core dumping signals */static void sig_coredump(int sig){ chdir(ap_coredump_dir); signal(sig, SIG_DFL); kill(getpid(), sig); /* At this point we've got sig blocked, because we're still inside * the signal handler. When we leave the signal handler it will * be unblocked, and we'll take the signal... and coredump or whatever * is appropriate for this particular Unix. In addition the parent * will see the real signal we received -- whereas if we called * abort() here, the parent would only see SIGABRT. */}/***************************************************************** * Connection structures and accounting... */static void just_die(int sig){ clean_child_exit(0);}static void usr1_handler(int sig){ if (THREAD_GLOBAL(usr1_just_die)) { just_die(sig); } thread_control[THREAD_GLOBAL(thread_num)].deferred_die = 1;}/* volatile just in case */static int volatile shutdown_pending;static int volatile restart_pending;static int volatile is_graceful;static void sig_term(int sig){ if (shutdown_pending == 1) { /* Um, is this _probably_ not an error, if the user has * tried to do a shutdown twice quickly, so we won't * worry about reporting it. */ return; } shutdown_pending = 1;}static void restart(int sig){ if (restart_pending == 1) { /* Probably not an error - don't bother reporting it */ return; } restart_pending = 1; is_graceful = sig == SIGUSR1;}static void set_signals(void){#ifndef NO_USE_SIGACTION struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (!one_process) { sa.sa_handler = sig_coredump;#if defined(SA_ONESHOT) sa.sa_flags = SA_ONESHOT;#elif defined(SA_RESETHAND) sa.sa_flags = SA_RESETHAND;#endif if (sigaction(SIGSEGV, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");#ifdef SIGBUS if (sigaction(SIGBUS, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");#endif#ifdef SIGABORT if (sigaction(SIGABORT, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");#endif#ifdef SIGABRT if (sigaction(SIGABRT, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");#endif#ifdef SIGILL if (sigaction(SIGILL, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");#endif sa.sa_flags = 0; } sa.sa_handler = sig_term; if (sigaction(SIGTERM, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");#ifdef SIGINT if (sigaction(SIGINT, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");#endif#ifdef SIGXCPU sa.sa_handler = SIG_DFL; if (sigaction(SIGXCPU, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");#endif#ifdef SIGXFSZ sa.sa_handler = SIG_DFL; if (sigaction(SIGXFSZ, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");#endif#ifdef SIGPIPE sa.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");#endif /* we want to ignore HUPs and USR1 while we're busy processing one */ sigaddset(&sa.sa_mask, SIGHUP); sigaddset(&sa.sa_mask, SIGUSR1); sa.sa_handler = restart; if (sigaction(SIGHUP, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)"); if (sigaction(SIGUSR1, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGUSR1)");#else if (!one_process) { signal(SIGSEGV, sig_coredump);#ifdef SIGBUS signal(SIGBUS, sig_coredump);#endif /* SIGBUS */#ifdef SIGABORT signal(SIGABORT, sig_coredump);#endif /* SIGABORT */#ifdef SIGABRT signal(SIGABRT, sig_coredump);#endif /* SIGABRT */#ifdef SIGILL signal(SIGILL, sig_coredump);#endif /* SIGILL */#ifdef SIGXCPU signal(SIGXCPU, SIG_DFL);#endif /* SIGXCPU */#ifdef SIGXFSZ signal(SIGXFSZ, SIG_DFL);#endif /* SIGXFSZ */ } signal(SIGTERM, sig_term);#ifdef SIGHUP signal(SIGHUP, restart);#endif /* SIGHUP */#ifdef SIGUSR1 signal(SIGUSR1, restart);#endif /* SIGUSR1 */#ifdef SIGPIPE signal(SIGPIPE, SIG_IGN);#endif /* SIGPIPE */#endif}/***************************************************************** * Child process main loop. */AP_DECLARE(void) ap_child_terminate(request_rec *r){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -