mirror of
https://github.com/apache/httpd.git
synced 2026-01-06 09:01:14 +03:00
remove OS/2 MPM
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@758899 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
2
LAYOUT
2
LAYOUT
@@ -161,8 +161,6 @@ server/ .................
|
||||
|
||||
event/ .................
|
||||
|
||||
mpmt_os2/ ...............
|
||||
|
||||
netware/ ................
|
||||
|
||||
prefork/ ................
|
||||
|
||||
@@ -18,12 +18,10 @@
|
||||
<IfModule !mpm_simple_module>
|
||||
<IfModule !mpm_winnt_module>
|
||||
<IfModule !mpm_netware_module>
|
||||
<IfModule !mpm_mpmt_os2_module>
|
||||
LockFile "@rel_logfiledir@/accept.lock"
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
||||
|
||||
#
|
||||
@@ -90,19 +88,6 @@ LockFile "@rel_logfiledir@/accept.lock"
|
||||
MaxMemFree 100
|
||||
</IfModule>
|
||||
|
||||
# OS/2 MPM
|
||||
# StartServers: Number of server processes to maintain
|
||||
# MinSpareThreads: Minimum number of idle threads per process,
|
||||
# to handle request spikes
|
||||
# MaxSpareThreads: Maximum number of idle threads per process
|
||||
# MaxRequestsPerChild: Maximum number of connections per server process
|
||||
<IfModule mpm_mpmt_os2_module>
|
||||
StartServers 2
|
||||
MinSpareThreads 5
|
||||
MaxSpareThreads 10
|
||||
MaxRequestsPerChild 0
|
||||
</IfModule>
|
||||
|
||||
# WinNT MPM
|
||||
# ThreadsPerChild: constant number of worker threads in the server process
|
||||
# MaxRequestsPerChild: maximum number of requests a server process serves
|
||||
|
||||
@@ -432,8 +432,7 @@
|
||||
<a href="../mpm.html">Multi-Processing Modules</a> (MPMs).
|
||||
When building Apache, you must choose an MPM to use. There
|
||||
are platform-specific MPMs for some platforms:
|
||||
<module>mpm_netware</module>,
|
||||
<module>mpmt_os2</module>, and <module>mpm_winnt</module>. For
|
||||
<module>mpm_netware</module> and <module>mpm_winnt</module>. For
|
||||
general Unix-type systems, there are several MPMs from which
|
||||
to choose. The choice of MPM can affect the speed and scalability
|
||||
of the httpd:</p>
|
||||
|
||||
@@ -199,7 +199,7 @@ of the daemon</description>
|
||||
<syntax>PidFile <var>filename</var></syntax>
|
||||
<default>PidFile logs/httpd.pid</default>
|
||||
<contextlist><context>server config</context></contextlist>
|
||||
<modulelist><module>mpm_winnt</module><module>mpmt_os2</module>
|
||||
<modulelist><module>mpm_winnt</module>
|
||||
<module>prefork</module><module>worker</module></modulelist>
|
||||
|
||||
<usage>
|
||||
@@ -238,7 +238,6 @@ listens to</description>
|
||||
<syntax>Listen [<var>IP-address</var>:]<var>portnumber</var> [<var>protocol</var>]</syntax>
|
||||
<contextlist><context>server config</context></contextlist>
|
||||
<modulelist><module>mpm_netware</module><module>mpm_winnt</module>
|
||||
<module>mpmt_os2</module>
|
||||
<module>prefork</module><module>worker</module>
|
||||
<module>event</module>
|
||||
</modulelist>
|
||||
@@ -321,7 +320,7 @@ The <var>protocol</var> argument was added in 2.1.5</compatibility>
|
||||
<contextlist><context>server config</context></contextlist>
|
||||
<modulelist>
|
||||
<module>mpm_netware</module><module>mpm_winnt</module>
|
||||
<module>mpmt_os2</module><module>prefork</module>
|
||||
<module>prefork</module>
|
||||
<module>worker</module></modulelist>
|
||||
|
||||
<usage>
|
||||
@@ -442,7 +441,7 @@ will handle during its life</description>
|
||||
<default>MaxRequestsPerChild 10000</default>
|
||||
<contextlist><context>server config</context></contextlist>
|
||||
<modulelist><module>mpm_netware</module>
|
||||
<module>mpm_winnt</module><module>mpmt_os2</module>
|
||||
<module>mpm_winnt</module>
|
||||
<module>prefork</module><module>worker</module></modulelist>
|
||||
|
||||
<usage>
|
||||
@@ -477,7 +476,7 @@ will handle during its life</description>
|
||||
<syntax>MaxSpareThreads <var>number</var></syntax>
|
||||
<default>See usage for details</default>
|
||||
<contextlist><context>server config</context></contextlist>
|
||||
<modulelist><module>mpm_netware</module><module>mpmt_os2</module>
|
||||
<modulelist><module>mpm_netware</module>
|
||||
<module>worker</module></modulelist>
|
||||
|
||||
<usage>
|
||||
@@ -494,10 +493,6 @@ will handle during its life</description>
|
||||
<code>MaxSpareThreads 100</code>. Since this MPM runs a
|
||||
single-process, the spare thread count is also server-wide.</p>
|
||||
|
||||
<p><module>mpmt_os2</module> works
|
||||
similar to <module>mpm_netware</module>. For
|
||||
<module>mpmt_os2</module> the default value is <code>10</code>.</p>
|
||||
|
||||
<note><title>Restrictions</title>
|
||||
<p>The range of the <directive>MaxSpareThreads</directive> value
|
||||
is restricted. Apache will correct the given value automatically
|
||||
@@ -523,7 +518,7 @@ spikes</description>
|
||||
<syntax>MinSpareThreads <var>number</var></syntax>
|
||||
<default>See usage for details</default>
|
||||
<contextlist><context>server config</context></contextlist>
|
||||
<modulelist><module>mpm_netware</module><module>mpmt_os2</module>
|
||||
<modulelist><module>mpm_netware</module>
|
||||
<module>worker</module></modulelist>
|
||||
|
||||
<usage>
|
||||
@@ -540,10 +535,6 @@ spikes</description>
|
||||
<p><module>mpm_netware</module> uses a default of
|
||||
<code>MinSpareThreads 10</code> and, since it is a single-process
|
||||
MPM, tracks this on a server-wide bases.</p>
|
||||
|
||||
<p><module>mpmt_os2</module> works
|
||||
similar to <module>mpm_netware</module>. For
|
||||
<module>mpmt_os2</module> the default value is <code>5</code>.</p>
|
||||
</usage>
|
||||
<seealso><directive module="mpm_common">MaxSpareThreads</directive></seealso>
|
||||
<seealso><directive module="mpm_common">StartServers</directive></seealso>
|
||||
@@ -591,7 +582,7 @@ Apache</a></seealso>
|
||||
<default>ReceiveBufferSize 0</default>
|
||||
<contextlist><context>server config</context></contextlist>
|
||||
<modulelist><module>mpm_netware</module><module>mpm_winnt</module>
|
||||
<module>mpmt_os2</module><module>prefork</module>
|
||||
<module>prefork</module>
|
||||
<module>worker</module></modulelist>
|
||||
|
||||
<usage>
|
||||
@@ -610,7 +601,7 @@ Apache</a></seealso>
|
||||
<default>SendBufferSize 0</default>
|
||||
<contextlist><context>server config</context></contextlist>
|
||||
<modulelist><module>mpm_netware</module><module>mpm_winnt</module>
|
||||
<module>mpmt_os2</module><module>prefork</module>
|
||||
<module>prefork</module>
|
||||
<module>worker</module></modulelist>
|
||||
|
||||
<usage>
|
||||
@@ -686,8 +677,7 @@ Apache</a></seealso>
|
||||
<syntax>StartServers <var>number</var></syntax>
|
||||
<default>See usage for details</default>
|
||||
<contextlist><context>server config</context></contextlist>
|
||||
<modulelist><module>mpmt_os2</module>
|
||||
<module>prefork</module><module>worker</module>
|
||||
<modulelist><module>prefork</module><module>worker</module>
|
||||
</modulelist>
|
||||
|
||||
<usage>
|
||||
@@ -698,8 +688,7 @@ Apache</a></seealso>
|
||||
|
||||
<p>The default value differs from MPM to MPM. <module>worker</module>
|
||||
defaults to <code>StartServers 3</code>; <module>prefork</module>
|
||||
defaults to <code>5</code>; <module>mpmt_os2</module> defaults to
|
||||
<code>2</code>.</p>
|
||||
defaults to <code>5</code>.</p>
|
||||
</usage>
|
||||
</directivesynopsis>
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# GENERATED FROM XML -- DO NOT EDIT
|
||||
|
||||
URI: mpmt_os2.html.en
|
||||
Content-Language: en
|
||||
Content-type: text/html; charset=ISO-8859-1
|
||||
@@ -1,73 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head><!--
|
||||
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
This file is generated from xml source: DO NOT EDIT
|
||||
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
-->
|
||||
<title>mpmt_os2 - Apache HTTP Server</title>
|
||||
<link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
|
||||
<link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
|
||||
<link href="../style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" />
|
||||
<link href="../images/favicon.ico" rel="shortcut icon" /></head>
|
||||
<body>
|
||||
<div id="page-header">
|
||||
<p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p>
|
||||
<p class="apache">Apache HTTP Server Version 2.3</p>
|
||||
<img alt="" src="../images/feather.gif" /></div>
|
||||
<div class="up"><a href="./"><img title="<-" alt="<-" src="../images/left.gif" /></a></div>
|
||||
<div id="path">
|
||||
<a href="http://www.apache.org/">Apache</a> > <a href="http://httpd.apache.org/">HTTP Server</a> > <a href="http://httpd.apache.org/docs/">Documentation</a> > <a href="../">Version 2.3</a> > <a href="./">Modules</a></div>
|
||||
<div id="page-content">
|
||||
<div id="preamble"><h1>Apache MPM os2</h1>
|
||||
<div class="toplang">
|
||||
<p><span>Available Languages: </span><a href="../en/mod/mpmt_os2.html" title="English"> en </a></p>
|
||||
</div>
|
||||
<table class="module"><tr><th><a href="module-dict.html#Description">Description:</a></th><td>Hybrid multi-process, multi-threaded MPM for OS/2</td></tr>
|
||||
<tr><th><a href="module-dict.html#Status">Status:</a></th><td>MPM</td></tr>
|
||||
<tr><th><a href="module-dict.html#ModuleIdentifier">Module<6C>Identifier:</a></th><td>mpm_mpmt_os2_module</td></tr>
|
||||
<tr><th><a href="module-dict.html#SourceFile">Source<63>File:</a></th><td>mpmt_os2.c</td></tr></table>
|
||||
<h3>Summary</h3>
|
||||
|
||||
<p>The Server consists of a main, parent process and a small, static
|
||||
number of child processes.</p>
|
||||
|
||||
<p>The parent process's job is to manage the child processes. This
|
||||
involves spawning children as required to ensure there are always
|
||||
<code class="directive"><a href="../mod/mpm_common.html#startservers">StartServers</a></code> processes
|
||||
accepting connections.</p>
|
||||
|
||||
<p>Each child process consists of a a pool of worker threads and a
|
||||
main thread that accepts connections and passes them to the workers via
|
||||
a work queue. The worker thread pool is dynamic, managed by a
|
||||
maintenance thread so that the number of idle threads is kept between
|
||||
<code class="directive"><a href="../mod/mpm_common.html#minsparethreads">MinSpareThreads</a></code> and
|
||||
<code class="directive"><a href="../mod/mpm_common.html#maxsparethreads">MaxSpareThreads</a></code>.</p>
|
||||
</div>
|
||||
<div id="quickview"><h3 class="directives">Directives</h3>
|
||||
<ul id="toc">
|
||||
<li><img alt="" src="../images/right.gif" /> <a href="mpm_common.html#group">Group</a></li>
|
||||
<li><img alt="" src="../images/right.gif" /> <a href="mpm_common.html#listen">Listen</a></li>
|
||||
<li><img alt="" src="../images/right.gif" /> <a href="mpm_common.html#listenbacklog">ListenBacklog</a></li>
|
||||
<li><img alt="" src="../images/right.gif" /> <a href="mpm_common.html#maxrequestsperchild">MaxRequestsPerChild</a></li>
|
||||
<li><img alt="" src="../images/right.gif" /> <a href="mpm_common.html#maxsparethreads">MaxSpareThreads</a></li>
|
||||
<li><img alt="" src="../images/right.gif" /> <a href="mpm_common.html#minsparethreads">MinSpareThreads</a></li>
|
||||
<li><img alt="" src="../images/right.gif" /> <a href="mpm_common.html#pidfile">PidFile</a></li>
|
||||
<li><img alt="" src="../images/right.gif" /> <a href="mpm_common.html#receivebuffersize">ReceiveBufferSize</a></li>
|
||||
<li><img alt="" src="../images/right.gif" /> <a href="mpm_common.html#sendbuffersize">SendBufferSize</a></li>
|
||||
<li><img alt="" src="../images/right.gif" /> <a href="mpm_common.html#startservers">StartServers</a></li>
|
||||
<li><img alt="" src="../images/right.gif" /> <a href="mpm_common.html#user">User</a></li>
|
||||
</ul>
|
||||
<h3>See also</h3>
|
||||
<ul class="seealso">
|
||||
<li><a href="../bind.html">Setting which addresses and ports Apache
|
||||
uses</a></li>
|
||||
</ul></div>
|
||||
|
||||
</div>
|
||||
<div class="bottomlang">
|
||||
<p><span>Available Languages: </span><a href="../en/mod/mpmt_os2.html" title="English"> en </a></p>
|
||||
</div><div id="footer">
|
||||
<p class="apache">Copyright 2009 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
|
||||
<p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div>
|
||||
</body></html>
|
||||
@@ -1,73 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
|
||||
<?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
|
||||
<!-- $LastChangedRevision$ -->
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<modulesynopsis metafile="mpmt_os2.xml.meta">
|
||||
|
||||
<name>mpmt_os2</name>
|
||||
<description>Hybrid multi-process, multi-threaded MPM for OS/2</description>
|
||||
<status>MPM</status>
|
||||
<sourcefile>mpmt_os2.c</sourcefile>
|
||||
<identifier>mpm_mpmt_os2_module</identifier>
|
||||
|
||||
<summary>
|
||||
<p>The Server consists of a main, parent process and a small, static
|
||||
number of child processes.</p>
|
||||
|
||||
<p>The parent process's job is to manage the child processes. This
|
||||
involves spawning children as required to ensure there are always
|
||||
<directive module="mpm_common">StartServers</directive> processes
|
||||
accepting connections.</p>
|
||||
|
||||
<p>Each child process consists of a a pool of worker threads and a
|
||||
main thread that accepts connections and passes them to the workers via
|
||||
a work queue. The worker thread pool is dynamic, managed by a
|
||||
maintenance thread so that the number of idle threads is kept between
|
||||
<directive module="mpm_common">MinSpareThreads</directive> and
|
||||
<directive module="mpm_common">MaxSpareThreads</directive>.</p>
|
||||
</summary>
|
||||
<seealso><a href="../bind.html">Setting which addresses and ports Apache
|
||||
uses</a></seealso>
|
||||
|
||||
<directivesynopsis location="mpm_common"><name>User</name>
|
||||
</directivesynopsis>
|
||||
<directivesynopsis location="mpm_common"><name>Group</name>
|
||||
</directivesynopsis>
|
||||
<directivesynopsis location="mpm_common"><name>Listen</name>
|
||||
</directivesynopsis>
|
||||
<directivesynopsis location="mpm_common"><name>ListenBacklog</name>
|
||||
</directivesynopsis>
|
||||
<directivesynopsis location="mpm_common"><name>ReceiveBufferSize</name>
|
||||
</directivesynopsis>
|
||||
<directivesynopsis location="mpm_common"><name>SendBufferSize</name>
|
||||
</directivesynopsis>
|
||||
<directivesynopsis location="mpm_common"><name>MaxRequestsPerChild</name>
|
||||
</directivesynopsis>
|
||||
<directivesynopsis location="mpm_common"><name>MaxSpareThreads</name>
|
||||
</directivesynopsis>
|
||||
<directivesynopsis location="mpm_common"><name>MinSpareThreads</name>
|
||||
</directivesynopsis>
|
||||
<directivesynopsis location="mpm_common"><name>PidFile</name>
|
||||
</directivesynopsis>
|
||||
<directivesynopsis location="mpm_common"><name>StartServers</name>
|
||||
</directivesynopsis>
|
||||
|
||||
</modulesynopsis>
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!-- GENERATED FROM XML: DO NOT EDIT -->
|
||||
|
||||
<metafile>
|
||||
<basename>mpmt_os2</basename>
|
||||
<path>/mod/</path>
|
||||
<relpath>..</relpath>
|
||||
|
||||
<variants>
|
||||
<variant>en</variant>
|
||||
</variants>
|
||||
</metafile>
|
||||
@@ -102,7 +102,6 @@ choice at compile-time.</p>
|
||||
<table>
|
||||
<columnspec><column width=".2"/><column width=".2"/></columnspec>
|
||||
<tr><td>Netware</td><td><module>mpm_netware</module></td></tr>
|
||||
<tr><td>OS/2</td><td><module>mpmt_os2</module></td></tr>
|
||||
<tr><td>Unix</td><td><module>prefork</module></td></tr>
|
||||
<tr><td>Windows</td><td><module>mpm_winnt</module></td></tr>
|
||||
</table>
|
||||
|
||||
@@ -5,9 +5,6 @@ The following MPMs currently exist:
|
||||
depending on configuration and operating systems. Should
|
||||
be able to run on all modern operating systems.
|
||||
prefork ....... Multi Process Model with Preforking (Apache 1.3)
|
||||
mpmt_os2 ...... Multi Process Model with Threading on OS/2
|
||||
Constant number of processes, variable number of threads.
|
||||
One acceptor thread per process, multiple workers threads.
|
||||
winnt ......... Single Process Model with Threading on Windows NT
|
||||
worker ........ Multi Process model with threads. One acceptor thread,
|
||||
multiple worker threads.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
LTLIBRARY_NAME = libmpmt_os2.la
|
||||
LTLIBRARY_SOURCES = mpmt_os2.c mpmt_os2_child.c
|
||||
|
||||
include $(top_srcdir)/build/ltlib.mk
|
||||
@@ -1,5 +0,0 @@
|
||||
if test "$MPM_NAME" = "mpmt_os2" ; then
|
||||
AC_CACHE_SAVE
|
||||
APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile)
|
||||
APR_ADDTO(CFLAGS,-Zmt)
|
||||
fi
|
||||
@@ -1,43 +0,0 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mpmt_os2/mpm.h
|
||||
* @brief MPM for os2
|
||||
*
|
||||
* @defgroup APACHE_MPM_OS2 os2 MPM
|
||||
* @ingroup APACHE_OS_OS2 APACHE_MPM
|
||||
*/
|
||||
|
||||
#ifndef APACHE_MPM_MPMT_OS2_H
|
||||
#define APACHE_MPM_MPMT_OS2_H
|
||||
|
||||
#define MPMT_OS2_MPM
|
||||
|
||||
#include "httpd.h"
|
||||
#include "mpm_default.h"
|
||||
#include "scoreboard.h"
|
||||
|
||||
#define MPM_NAME "MPMT_OS2"
|
||||
|
||||
extern server_rec *ap_server_conf;
|
||||
#define AP_MPM_WANT_SET_PIDFILE
|
||||
#define AP_MPM_WANT_SET_MAX_REQUESTS
|
||||
#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
|
||||
#define AP_MPM_WANT_SET_MAX_MEM_FREE
|
||||
|
||||
#endif /* APACHE_MPM_MPMT_OS2_H */
|
||||
/** @} */
|
||||
@@ -1,68 +0,0 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mpmt_os2/mpm_default.h
|
||||
* @brief os2 MPM defaults
|
||||
*
|
||||
* @addtogroup APACHE_MPM_OS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef APACHE_MPM_DEFAULT_H
|
||||
#define APACHE_MPM_DEFAULT_H
|
||||
|
||||
/* Number of servers processes to spawn off by default
|
||||
*/
|
||||
#ifndef DEFAULT_START_DAEMON
|
||||
#define DEFAULT_START_DAEMON 2
|
||||
#endif
|
||||
|
||||
/* Maximum number of *free* server threads --- more than this, and
|
||||
* they will die off.
|
||||
*/
|
||||
|
||||
#ifndef DEFAULT_MAX_SPARE_THREAD
|
||||
#define DEFAULT_MAX_SPARE_THREAD 10
|
||||
#endif
|
||||
|
||||
/* Minimum --- fewer than this, and more will be created */
|
||||
|
||||
#ifndef DEFAULT_MIN_SPARE_THREAD
|
||||
#define DEFAULT_MIN_SPARE_THREAD 5
|
||||
#endif
|
||||
|
||||
/* Where the main/parent process's pid is logged */
|
||||
#ifndef DEFAULT_PIDLOG
|
||||
#define DEFAULT_PIDLOG DEFAULT_REL_RUNTIMEDIR "/httpd.pid"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interval, in microseconds, between scoreboard maintenance.
|
||||
*/
|
||||
#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
|
||||
#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
|
||||
#endif
|
||||
|
||||
/* Number of requests to try to handle in a single process. If <= 0,
|
||||
* the children don't die off.
|
||||
*/
|
||||
#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
|
||||
#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
|
||||
#endif
|
||||
|
||||
#endif /* AP_MPM_DEFAULT_H */
|
||||
/** @} */
|
||||
@@ -1,606 +0,0 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Multi-process, multi-threaded MPM for OS/2
|
||||
*
|
||||
* Server consists of
|
||||
* - a main, parent process
|
||||
* - a small, static number of child processes
|
||||
*
|
||||
* The parent process's job is to manage the child processes. This involves
|
||||
* spawning children as required to ensure there are always ap_daemons_to_start
|
||||
* processes accepting connections.
|
||||
*
|
||||
* Each child process consists of a a pool of worker threads and a
|
||||
* main thread that accepts connections & passes them to the workers via
|
||||
* a work queue. The worker thread pool is dynamic, managed by a maintanence
|
||||
* thread so that the number of idle threads is kept between
|
||||
* min_spare_threads & max_spare_threads.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Todo list
|
||||
- Enforce MaxClients somehow
|
||||
*/
|
||||
#define INCL_NOPMAPI
|
||||
#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 <process.h>
|
||||
|
||||
/* We don't need many processes,
|
||||
* they're only for redundancy in the event of a crash
|
||||
*/
|
||||
#define HARD_SERVER_LIMIT 10
|
||||
|
||||
/* Limit on the total number of threads per process
|
||||
*/
|
||||
#ifndef HARD_THREAD_LIMIT
|
||||
#define HARD_THREAD_LIMIT 256
|
||||
#endif
|
||||
|
||||
server_rec *ap_server_conf;
|
||||
static apr_pool_t *pconf = NULL; /* Pool for config stuff */
|
||||
static const char *ap_pid_fname=NULL;
|
||||
|
||||
/* Config globals */
|
||||
static int one_process = 0;
|
||||
static int ap_daemons_to_start = 0;
|
||||
static int ap_thread_limit = 0;
|
||||
static int ap_max_requests_per_child = 0;
|
||||
int ap_min_spare_threads = 0;
|
||||
int ap_max_spare_threads = 0;
|
||||
|
||||
/* Keep track of a few interesting statistics */
|
||||
int ap_max_daemons_limit = -1;
|
||||
|
||||
/* volatile just in case */
|
||||
static int volatile shutdown_pending;
|
||||
static int volatile restart_pending;
|
||||
static int volatile is_graceful = 0;
|
||||
ap_generation_t volatile ap_my_generation=0; /* Used by the scoreboard */
|
||||
static int is_parent_process=TRUE;
|
||||
HMTX ap_mpm_accept_mutex = 0;
|
||||
|
||||
/* An array of these is stored in a shared memory area for passing
|
||||
* sockets from the parent to child processes
|
||||
*/
|
||||
typedef struct {
|
||||
struct sockaddr_in name;
|
||||
apr_os_sock_t listen_fd;
|
||||
} listen_socket_t;
|
||||
|
||||
typedef struct {
|
||||
HMTX accept_mutex;
|
||||
listen_socket_t listeners[1];
|
||||
} parent_info_t;
|
||||
|
||||
static char master_main();
|
||||
static void spawn_child(int slot);
|
||||
void ap_mpm_child_main(apr_pool_t *pconf);
|
||||
static void set_signals();
|
||||
|
||||
|
||||
int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s )
|
||||
{
|
||||
char *listener_shm_name;
|
||||
parent_info_t *parent_info;
|
||||
ULONG rc;
|
||||
pconf = _pconf;
|
||||
ap_server_conf = s;
|
||||
restart_pending = 0;
|
||||
|
||||
DosSetMaxFH(ap_thread_limit * 2);
|
||||
listener_shm_name = apr_psprintf(pconf, "/sharemem/httpd/parent_info.%d", getppid());
|
||||
rc = DosGetNamedSharedMem((PPVOID)&parent_info, listener_shm_name, PAG_READ);
|
||||
is_parent_process = rc != 0;
|
||||
ap_scoreboard_fname = apr_psprintf(pconf, "/sharemem/httpd/scoreboard.%d", is_parent_process ? getpid() : getppid());
|
||||
|
||||
if (rc == 0) {
|
||||
/* Child process */
|
||||
ap_listen_rec *lr;
|
||||
int num_listeners = 0;
|
||||
|
||||
ap_mpm_accept_mutex = parent_info->accept_mutex;
|
||||
|
||||
/* Set up a default listener if necessary */
|
||||
if (ap_listeners == NULL) {
|
||||
ap_listen_rec *lr = apr_pcalloc(s->process->pool, sizeof(ap_listen_rec));
|
||||
ap_listeners = lr;
|
||||
apr_sockaddr_info_get(&lr->bind_addr, "0.0.0.0", APR_UNSPEC,
|
||||
DEFAULT_HTTP_PORT, 0, s->process->pool);
|
||||
apr_socket_create(&lr->sd, lr->bind_addr->family,
|
||||
SOCK_STREAM, 0, s->process->pool);
|
||||
}
|
||||
|
||||
for (lr = ap_listeners; lr; lr = lr->next) {
|
||||
apr_sockaddr_t *sa;
|
||||
apr_os_sock_put(&lr->sd, &parent_info->listeners[num_listeners].listen_fd, pconf);
|
||||
apr_socket_addr_get(&sa, APR_LOCAL, lr->sd);
|
||||
num_listeners++;
|
||||
}
|
||||
|
||||
DosFreeMem(parent_info);
|
||||
|
||||
/* Do the work */
|
||||
ap_mpm_child_main(pconf);
|
||||
|
||||
/* Outta here */
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
/* Parent process */
|
||||
char restart;
|
||||
is_parent_process = TRUE;
|
||||
|
||||
if (ap_setup_listeners(ap_server_conf) < 1) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, 0, s,
|
||||
"no listening sockets available, shutting down");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ap_log_pid(pconf, ap_pid_fname);
|
||||
|
||||
restart = master_main();
|
||||
++ap_my_generation;
|
||||
ap_scoreboard_image->global->running_generation = ap_my_generation;
|
||||
|
||||
if (!restart) {
|
||||
const char *pidfile = ap_server_root_relative(pconf, ap_pid_fname);
|
||||
|
||||
if (pidfile != NULL && remove(pidfile) == 0) {
|
||||
ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS,
|
||||
ap_server_conf, "removed PID file %s (pid=%d)",
|
||||
pidfile, getpid());
|
||||
}
|
||||
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
|
||||
"caught SIGTERM, shutting down");
|
||||
return 1;
|
||||
}
|
||||
} /* Parent process */
|
||||
|
||||
return 0; /* Restart */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Main processing of the parent process
|
||||
* returns TRUE if restarting
|
||||
*/
|
||||
static char master_main()
|
||||
{
|
||||
server_rec *s = ap_server_conf;
|
||||
ap_listen_rec *lr;
|
||||
parent_info_t *parent_info;
|
||||
char *listener_shm_name;
|
||||
int listener_num, num_listeners, slot;
|
||||
ULONG rc;
|
||||
|
||||
printf("%s \n", ap_get_server_description());
|
||||
set_signals();
|
||||
|
||||
if (ap_setup_listeners(ap_server_conf) < 1) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, 0, s,
|
||||
"no listening sockets available, shutting down");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Allocate a shared memory block for the array of listeners */
|
||||
for (num_listeners = 0, lr = ap_listeners; lr; lr = lr->next) {
|
||||
num_listeners++;
|
||||
}
|
||||
|
||||
listener_shm_name = apr_psprintf(pconf, "/sharemem/httpd/parent_info.%d", getpid());
|
||||
rc = DosAllocSharedMem((PPVOID)&parent_info, listener_shm_name,
|
||||
sizeof(parent_info_t) + num_listeners * sizeof(listen_socket_t),
|
||||
PAG_READ|PAG_WRITE|PAG_COMMIT);
|
||||
|
||||
if (rc) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, APR_FROM_OS_ERROR(rc), s,
|
||||
"failure allocating shared memory, shutting down");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Store the listener sockets in the shared memory area for our children to see */
|
||||
for (listener_num = 0, lr = ap_listeners; lr; lr = lr->next, listener_num++) {
|
||||
apr_os_sock_get(&parent_info->listeners[listener_num].listen_fd, lr->sd);
|
||||
}
|
||||
|
||||
/* Create mutex to prevent multiple child processes from detecting
|
||||
* a connection with apr_poll()
|
||||
*/
|
||||
|
||||
rc = DosCreateMutexSem(NULL, &ap_mpm_accept_mutex, DC_SEM_SHARED, FALSE);
|
||||
|
||||
if (rc) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, APR_FROM_OS_ERROR(rc), s,
|
||||
"failure creating accept mutex, shutting down");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
parent_info->accept_mutex = ap_mpm_accept_mutex;
|
||||
|
||||
/* Allocate shared memory for scoreboard */
|
||||
if (ap_scoreboard_image == NULL) {
|
||||
void *sb_mem;
|
||||
rc = DosAllocSharedMem(&sb_mem, ap_scoreboard_fname,
|
||||
ap_calc_scoreboard_size(),
|
||||
PAG_COMMIT|PAG_READ|PAG_WRITE);
|
||||
|
||||
if (rc) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
|
||||
"unable to allocate shared memory for scoreboard , exiting");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ap_init_scoreboard(sb_mem);
|
||||
}
|
||||
|
||||
ap_scoreboard_image->global->restart_time = apr_time_now();
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
|
||||
"%s configured -- resuming normal operations",
|
||||
ap_get_server_description());
|
||||
ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
|
||||
"Server built: %s", ap_get_server_built());
|
||||
#ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
|
||||
"AcceptMutex: %s (default: %s)",
|
||||
apr_proc_mutex_name(accept_mutex),
|
||||
apr_proc_mutex_defname());
|
||||
#endif
|
||||
if (one_process) {
|
||||
ap_scoreboard_image->parent[0].pid = getpid();
|
||||
ap_mpm_child_main(pconf);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (!restart_pending && !shutdown_pending) {
|
||||
RESULTCODES proc_rc;
|
||||
PID child_pid;
|
||||
int active_children = 0;
|
||||
|
||||
/* Count number of active children */
|
||||
for (slot=0; slot < HARD_SERVER_LIMIT; slot++) {
|
||||
active_children += ap_scoreboard_image->parent[slot].pid != 0 &&
|
||||
!ap_scoreboard_image->parent[slot].quiescing;
|
||||
}
|
||||
|
||||
/* Spawn children if needed */
|
||||
for (slot=0; slot < HARD_SERVER_LIMIT && active_children < ap_daemons_to_start; slot++) {
|
||||
if (ap_scoreboard_image->parent[slot].pid == 0) {
|
||||
spawn_child(slot);
|
||||
active_children++;
|
||||
}
|
||||
}
|
||||
|
||||
rc = DosWaitChild(DCWA_PROCESSTREE, DCWW_NOWAIT, &proc_rc, &child_pid, 0);
|
||||
|
||||
if (rc == 0) {
|
||||
/* A child has terminated, remove its scoreboard entry & terminate if necessary */
|
||||
for (slot=0; ap_scoreboard_image->parent[slot].pid != child_pid && slot < HARD_SERVER_LIMIT; slot++);
|
||||
|
||||
if (slot < HARD_SERVER_LIMIT) {
|
||||
ap_scoreboard_image->parent[slot].pid = 0;
|
||||
ap_scoreboard_image->parent[slot].quiescing = 0;
|
||||
|
||||
if (proc_rc.codeTerminate == TC_EXIT) {
|
||||
/* Child terminated normally, check its exit code and
|
||||
* terminate server if child indicates a fatal error
|
||||
*/
|
||||
if (proc_rc.codeResult == APEXIT_CHILDFATAL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (rc == ERROR_CHILD_NOT_COMPLETE) {
|
||||
/* No child exited, lets sleep for a while.... */
|
||||
apr_sleep(SCOREBOARD_MAINTENANCE_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Signal children to shut down, either gracefully or immediately */
|
||||
for (slot=0; slot<HARD_SERVER_LIMIT; slot++) {
|
||||
kill(ap_scoreboard_image->parent[slot].pid, is_graceful ? SIGHUP : SIGTERM);
|
||||
}
|
||||
|
||||
DosFreeMem(parent_info);
|
||||
return restart_pending;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void spawn_child(int slot)
|
||||
{
|
||||
PPIB ppib;
|
||||
PTIB ptib;
|
||||
char fail_module[100];
|
||||
char progname[CCHMAXPATH];
|
||||
RESULTCODES proc_rc;
|
||||
ULONG rc;
|
||||
|
||||
ap_scoreboard_image->parent[slot].generation = ap_my_generation;
|
||||
DosGetInfoBlocks(&ptib, &ppib);
|
||||
DosQueryModuleName(ppib->pib_hmte, sizeof(progname), progname);
|
||||
rc = DosExecPgm(fail_module, sizeof(fail_module), EXEC_ASYNCRESULT,
|
||||
ppib->pib_pchcmd, NULL, &proc_rc, progname);
|
||||
|
||||
if (rc) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
|
||||
"error spawning child, slot %d", slot);
|
||||
}
|
||||
|
||||
if (ap_max_daemons_limit < slot) {
|
||||
ap_max_daemons_limit = slot;
|
||||
}
|
||||
|
||||
ap_scoreboard_image->parent[slot].pid = proc_rc.codeTerminate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Signal handling routines */
|
||||
|
||||
static void sig_term(int sig)
|
||||
{
|
||||
shutdown_pending = 1;
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void sig_restart(int sig)
|
||||
{
|
||||
if (sig == SIGUSR1) {
|
||||
is_graceful = 1;
|
||||
}
|
||||
|
||||
restart_pending = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void set_signals()
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
sigemptyset(&sa.sa_mask);
|
||||
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)");
|
||||
|
||||
if (sigaction(SIGINT, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
|
||||
|
||||
sa.sa_handler = sig_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)");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Enquiry functions used get MPM status info */
|
||||
|
||||
AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
|
||||
{
|
||||
switch (query_code) {
|
||||
case AP_MPMQ_MAX_DAEMON_USED:
|
||||
*result = ap_max_daemons_limit;
|
||||
return APR_SUCCESS;
|
||||
case AP_MPMQ_IS_THREADED:
|
||||
*result = AP_MPMQ_DYNAMIC;
|
||||
return APR_SUCCESS;
|
||||
case AP_MPMQ_IS_FORKED:
|
||||
*result = AP_MPMQ_NOT_SUPPORTED;
|
||||
return APR_SUCCESS;
|
||||
case AP_MPMQ_HARD_LIMIT_DAEMONS:
|
||||
*result = HARD_SERVER_LIMIT;
|
||||
return APR_SUCCESS;
|
||||
case AP_MPMQ_HARD_LIMIT_THREADS:
|
||||
*result = HARD_THREAD_LIMIT;
|
||||
return APR_SUCCESS;
|
||||
case AP_MPMQ_MIN_SPARE_DAEMONS:
|
||||
*result = 0;
|
||||
return APR_SUCCESS;
|
||||
case AP_MPMQ_MAX_SPARE_DAEMONS:
|
||||
*result = 0;
|
||||
return APR_SUCCESS;
|
||||
case AP_MPMQ_MAX_REQUESTS_DAEMON:
|
||||
*result = ap_max_requests_per_child;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
return APR_ENOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Configuration handling stuff */
|
||||
|
||||
static int mpmt_os2_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
|
||||
{
|
||||
one_process = ap_exists_config_define("ONE_PROCESS") ||
|
||||
ap_exists_config_define("DEBUG");
|
||||
is_graceful = 0;
|
||||
ap_listen_pre_config();
|
||||
ap_daemons_to_start = DEFAULT_START_DAEMON;
|
||||
ap_thread_limit = HARD_THREAD_LIMIT;
|
||||
ap_pid_fname = DEFAULT_PIDLOG;
|
||||
ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
|
||||
ap_extended_status = 0;
|
||||
ap_min_spare_threads = DEFAULT_MIN_SPARE_THREAD;
|
||||
ap_max_spare_threads = DEFAULT_MAX_SPARE_THREAD;
|
||||
#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
|
||||
ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int mpmt_os2_check_config(apr_pool_t *p, apr_pool_t *plog,
|
||||
apr_pool_t *ptemp, server_rec *s)
|
||||
{
|
||||
static int restart_num = 0;
|
||||
int startup = 0;
|
||||
|
||||
/* we want this only the first time around */
|
||||
if (restart_num++ == 0) {
|
||||
startup = 1;
|
||||
}
|
||||
|
||||
if (ap_daemons_to_start < 0) {
|
||||
if (startup) {
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
|
||||
"WARNING: StartServers of %d not allowed, "
|
||||
"increasing to 1.", ap_daemons_to_start);
|
||||
} else {
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
|
||||
"StartServers of %d not allowed, increasing to 1",
|
||||
ap_daemons_to_start);
|
||||
}
|
||||
ap_daemons_to_start = 1;
|
||||
}
|
||||
|
||||
if (ap_min_spare_threads < 1) {
|
||||
if (startup) {
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
|
||||
"WARNING: MinSpareThreads of %d not allowed, "
|
||||
"increasing to 1", ap_min_spare_threads);
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
|
||||
" to avoid almost certain server failure.");
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
|
||||
" Please read the documentation.");
|
||||
} else {
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
|
||||
"MinSpareThreads of %d not allowed, increasing to 1",
|
||||
ap_min_spare_threads);
|
||||
}
|
||||
ap_min_spare_threads = 1;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void mpmt_os2_hooks(apr_pool_t *p)
|
||||
{
|
||||
ap_hook_pre_config(mpmt_os2_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_check_config(mpmt_os2_check_config, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
|
||||
{
|
||||
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
|
||||
|
||||
if (err != NULL) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ap_daemons_to_start = atoi(arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy,
|
||||
const char *arg)
|
||||
{
|
||||
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
|
||||
|
||||
if (err != NULL) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ap_min_spare_threads = atoi(arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy,
|
||||
const char *arg)
|
||||
{
|
||||
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
|
||||
|
||||
if (err != NULL) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ap_max_spare_threads = atoi(arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char *ignore_cmd(cmd_parms *cmd, void *dummy, const char *arg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const command_rec mpmt_os2_cmds[] = {
|
||||
LISTEN_COMMANDS,
|
||||
AP_INIT_TAKE1( "StartServers", set_daemons_to_start, NULL, RSRC_CONF,
|
||||
"Number of child processes launched at server startup" ),
|
||||
AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
|
||||
"Minimum number of idle children, to handle request spikes"),
|
||||
AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
|
||||
"Maximum number of idle children"),
|
||||
AP_INIT_TAKE1("User", ignore_cmd, NULL, RSRC_CONF,
|
||||
"Not applicable on this platform"),
|
||||
AP_INIT_TAKE1("Group", ignore_cmd, NULL, RSRC_CONF,
|
||||
"Not applicable on this platform"),
|
||||
AP_INIT_TAKE1("ScoreBoardFile", ignore_cmd, NULL, RSRC_CONF, \
|
||||
"Not applicable on this platform"),
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
module AP_MODULE_DECLARE_DATA mpm_mpmt_os2_module = {
|
||||
MPM20_MODULE_STUFF,
|
||||
NULL, /* hook to run before apache parses args */
|
||||
NULL, /* create per-directory config structure */
|
||||
NULL, /* merge per-directory config structures */
|
||||
NULL, /* create per-server config structure */
|
||||
NULL, /* merge per-server config structures */
|
||||
mpmt_os2_cmds, /* command apr_table_t */
|
||||
mpmt_os2_hooks, /* register_hooks */
|
||||
};
|
||||
@@ -1,479 +0,0 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define INCL_NOPMAPI
|
||||
#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 "apr_poll.h"
|
||||
#include "mpm_common.h"
|
||||
#include "apr_strings.h"
|
||||
#include <os2.h>
|
||||
#include <process.h>
|
||||
|
||||
/* XXXXXX move these to header file private to this MPM */
|
||||
|
||||
/* We don't need many processes,
|
||||
* they're only for redundancy in the event of a crash
|
||||
*/
|
||||
#define HARD_SERVER_LIMIT 10
|
||||
|
||||
/* Limit on the total number of threads per process
|
||||
*/
|
||||
#ifndef HARD_THREAD_LIMIT
|
||||
#define HARD_THREAD_LIMIT 256
|
||||
#endif
|
||||
|
||||
#define ID_FROM_CHILD_THREAD(c, t) ((c * HARD_THREAD_LIMIT) + t)
|
||||
|
||||
typedef struct {
|
||||
apr_pool_t *pconn;
|
||||
apr_socket_t *conn_sd;
|
||||
} worker_args_t;
|
||||
|
||||
#define WORKTYPE_CONN 0
|
||||
#define WORKTYPE_EXIT 1
|
||||
|
||||
static apr_pool_t *pchild = NULL;
|
||||
static int child_slot;
|
||||
static int shutdown_pending = 0;
|
||||
extern int ap_my_generation;
|
||||
static int volatile is_graceful = 1;
|
||||
HEV shutdown_event; /* signaled when this child is shutting down */
|
||||
|
||||
/* grab some MPM globals */
|
||||
extern int ap_min_spare_threads;
|
||||
extern int ap_max_spare_threads;
|
||||
extern HMTX ap_mpm_accept_mutex;
|
||||
|
||||
static void worker_main(void *vpArg);
|
||||
static void clean_child_exit(int code);
|
||||
static void set_signals();
|
||||
static void server_maintenance(void *vpArg);
|
||||
|
||||
|
||||
static void clean_child_exit(int code)
|
||||
{
|
||||
if (pchild) {
|
||||
apr_pool_destroy(pchild);
|
||||
}
|
||||
|
||||
exit(code);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ap_mpm_child_main(apr_pool_t *pconf)
|
||||
{
|
||||
ap_listen_rec *lr = NULL;
|
||||
int requests_this_child = 0;
|
||||
int rv = 0;
|
||||
unsigned long ulTimes;
|
||||
int my_pid = getpid();
|
||||
ULONG rc, c;
|
||||
HQUEUE workq;
|
||||
apr_pollset_t *pollset;
|
||||
int num_listeners;
|
||||
TID server_maint_tid;
|
||||
void *sb_mem;
|
||||
|
||||
/* Stop Ctrl-C/Ctrl-Break signals going to child processes */
|
||||
DosSetSignalExceptionFocus(0, &ulTimes);
|
||||
set_signals();
|
||||
|
||||
/* Create pool for child */
|
||||
apr_pool_create(&pchild, pconf);
|
||||
|
||||
ap_run_child_init(pchild, ap_server_conf);
|
||||
|
||||
/* Create an event semaphore used to trigger other threads to shutdown */
|
||||
rc = DosCreateEventSem(NULL, &shutdown_event, 0, FALSE);
|
||||
|
||||
if (rc) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
|
||||
"unable to create shutdown semaphore, exiting");
|
||||
clean_child_exit(APEXIT_CHILDFATAL);
|
||||
}
|
||||
|
||||
/* Gain access to the scoreboard. */
|
||||
rc = DosGetNamedSharedMem(&sb_mem, ap_scoreboard_fname,
|
||||
PAG_READ|PAG_WRITE);
|
||||
|
||||
if (rc) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
|
||||
"scoreboard not readable in child, exiting");
|
||||
clean_child_exit(APEXIT_CHILDFATAL);
|
||||
}
|
||||
|
||||
ap_calc_scoreboard_size();
|
||||
ap_init_scoreboard(sb_mem);
|
||||
|
||||
/* Gain access to the accpet mutex */
|
||||
rc = DosOpenMutexSem(NULL, &ap_mpm_accept_mutex);
|
||||
|
||||
if (rc) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
|
||||
"accept mutex couldn't be accessed in child, exiting");
|
||||
clean_child_exit(APEXIT_CHILDFATAL);
|
||||
}
|
||||
|
||||
/* Find our pid in the scoreboard so we know what slot our parent allocated us */
|
||||
for (child_slot = 0; ap_scoreboard_image->parent[child_slot].pid != my_pid && child_slot < HARD_SERVER_LIMIT; child_slot++);
|
||||
|
||||
if (child_slot == HARD_SERVER_LIMIT) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
|
||||
"child pid not found in scoreboard, exiting");
|
||||
clean_child_exit(APEXIT_CHILDFATAL);
|
||||
}
|
||||
|
||||
ap_my_generation = ap_scoreboard_image->parent[child_slot].generation;
|
||||
memset(ap_scoreboard_image->servers[child_slot], 0, sizeof(worker_score) * HARD_THREAD_LIMIT);
|
||||
|
||||
/* Set up an OS/2 queue for passing connections & termination requests
|
||||
* to worker threads
|
||||
*/
|
||||
rc = DosCreateQueue(&workq, QUE_FIFO, apr_psprintf(pchild, "/queues/httpd/work.%d", my_pid));
|
||||
|
||||
if (rc) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
|
||||
"unable to create work queue, exiting");
|
||||
clean_child_exit(APEXIT_CHILDFATAL);
|
||||
}
|
||||
|
||||
/* Create initial pool of worker threads */
|
||||
for (c = 0; c < ap_min_spare_threads; c++) {
|
||||
// ap_scoreboard_image->servers[child_slot][c].tid = _beginthread(worker_main, NULL, 128*1024, (void *)c);
|
||||
}
|
||||
|
||||
/* Start maintenance thread */
|
||||
server_maint_tid = _beginthread(server_maintenance, NULL, 32768, NULL);
|
||||
|
||||
/* Set up poll */
|
||||
for (num_listeners = 0, lr = ap_listeners; lr; lr = lr->next) {
|
||||
num_listeners++;
|
||||
}
|
||||
|
||||
apr_pollset_create(&pollset, num_listeners, pchild, 0);
|
||||
|
||||
for (lr = ap_listeners; lr != NULL; lr = lr->next) {
|
||||
apr_pollfd_t pfd = { 0 };
|
||||
|
||||
pfd.desc_type = APR_POLL_SOCKET;
|
||||
pfd.desc.s = lr->sd;
|
||||
pfd.reqevents = APR_POLLIN;
|
||||
pfd.client_data = lr;
|
||||
apr_pollset_add(pollset, &pfd);
|
||||
}
|
||||
|
||||
/* Main connection accept loop */
|
||||
do {
|
||||
apr_pool_t *pconn;
|
||||
worker_args_t *worker_args;
|
||||
int last_poll_idx = 0;
|
||||
|
||||
apr_pool_create(&pconn, pchild);
|
||||
worker_args = apr_palloc(pconn, sizeof(worker_args_t));
|
||||
worker_args->pconn = pconn;
|
||||
|
||||
if (num_listeners == 1) {
|
||||
rv = apr_socket_accept(&worker_args->conn_sd, ap_listeners->sd, pconn);
|
||||
} else {
|
||||
const apr_pollfd_t *poll_results;
|
||||
apr_int32_t num_poll_results;
|
||||
|
||||
rc = DosRequestMutexSem(ap_mpm_accept_mutex, SEM_INDEFINITE_WAIT);
|
||||
|
||||
if (shutdown_pending) {
|
||||
DosReleaseMutexSem(ap_mpm_accept_mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
rv = APR_FROM_OS_ERROR(rc);
|
||||
|
||||
if (rv == APR_SUCCESS) {
|
||||
rv = apr_pollset_poll(pollset, -1, &num_poll_results, &poll_results);
|
||||
DosReleaseMutexSem(ap_mpm_accept_mutex);
|
||||
}
|
||||
|
||||
if (rv == APR_SUCCESS) {
|
||||
if (last_poll_idx >= num_listeners) {
|
||||
last_poll_idx = 0;
|
||||
}
|
||||
|
||||
lr = poll_results[last_poll_idx++].client_data;
|
||||
rv = apr_socket_accept(&worker_args->conn_sd, lr->sd, pconn);
|
||||
last_poll_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv != APR_SUCCESS) {
|
||||
if (!APR_STATUS_IS_EINTR(rv)) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
|
||||
"apr_socket_accept");
|
||||
clean_child_exit(APEXIT_CHILDFATAL);
|
||||
}
|
||||
} else {
|
||||
DosWriteQueue(workq, WORKTYPE_CONN, sizeof(worker_args_t), worker_args, 0);
|
||||
requests_this_child++;
|
||||
}
|
||||
|
||||
if (ap_max_requests_per_child != 0 && requests_this_child >= ap_max_requests_per_child)
|
||||
break;
|
||||
} while (!shutdown_pending && ap_my_generation == ap_scoreboard_image->global->running_generation);
|
||||
|
||||
ap_scoreboard_image->parent[child_slot].quiescing = 1;
|
||||
DosPostEventSem(shutdown_event);
|
||||
DosWaitThread(&server_maint_tid, DCWW_WAIT);
|
||||
|
||||
if (is_graceful) {
|
||||
char someleft;
|
||||
|
||||
/* tell our worker threads to exit */
|
||||
for (c=0; c<HARD_THREAD_LIMIT; c++) {
|
||||
if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
|
||||
DosWriteQueue(workq, WORKTYPE_EXIT, 0, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
someleft = 0;
|
||||
|
||||
for (c=0; c<HARD_THREAD_LIMIT; c++) {
|
||||
if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
|
||||
someleft = 1;
|
||||
DosSleep(1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (someleft);
|
||||
} else {
|
||||
DosPurgeQueue(workq);
|
||||
|
||||
for (c=0; c<HARD_THREAD_LIMIT; c++) {
|
||||
if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
|
||||
DosKillThread(ap_scoreboard_image->servers[child_slot][c].tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apr_pool_destroy(pchild);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void add_worker()
|
||||
{
|
||||
int thread_slot;
|
||||
|
||||
/* Find a free thread slot */
|
||||
for (thread_slot=0; thread_slot < HARD_THREAD_LIMIT; thread_slot++) {
|
||||
if (ap_scoreboard_image->servers[child_slot][thread_slot].status == SERVER_DEAD) {
|
||||
ap_scoreboard_image->servers[child_slot][thread_slot].status = SERVER_STARTING;
|
||||
ap_scoreboard_image->servers[child_slot][thread_slot].tid =
|
||||
_beginthread(worker_main, NULL, 128*1024, (void *)thread_slot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ULONG APIENTRY thread_exception_handler(EXCEPTIONREPORTRECORD *pReportRec,
|
||||
EXCEPTIONREGISTRATIONRECORD *pRegRec,
|
||||
CONTEXTRECORD *pContext,
|
||||
PVOID p)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (pReportRec->fHandlerFlags & EH_NESTED_CALL) {
|
||||
return XCPT_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
if (pReportRec->ExceptionNum == XCPT_ACCESS_VIOLATION ||
|
||||
pReportRec->ExceptionNum == XCPT_INTEGER_DIVIDE_BY_ZERO) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
|
||||
"caught exception in worker thread, initiating child shutdown pid=%d", getpid());
|
||||
for (c=0; c<HARD_THREAD_LIMIT; c++) {
|
||||
if (ap_scoreboard_image->servers[child_slot][c].tid == _gettid()) {
|
||||
ap_scoreboard_image->servers[child_slot][c].status = SERVER_DEAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shut down process ASAP, it could be quite unhealthy & leaking resources */
|
||||
shutdown_pending = 1;
|
||||
ap_scoreboard_image->parent[child_slot].quiescing = 1;
|
||||
kill(getpid(), SIGHUP);
|
||||
DosUnwindException(UNWIND_ALL, 0, 0);
|
||||
}
|
||||
|
||||
return XCPT_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void worker_main(void *vpArg)
|
||||
{
|
||||
long conn_id;
|
||||
conn_rec *current_conn;
|
||||
apr_pool_t *pconn;
|
||||
apr_allocator_t *allocator;
|
||||
apr_bucket_alloc_t *bucket_alloc;
|
||||
worker_args_t *worker_args;
|
||||
HQUEUE workq;
|
||||
PID owner;
|
||||
int rc;
|
||||
REQUESTDATA rd;
|
||||
ULONG len;
|
||||
BYTE priority;
|
||||
int thread_slot = (int)vpArg;
|
||||
EXCEPTIONREGISTRATIONRECORD reg_rec = { NULL, thread_exception_handler };
|
||||
ap_sb_handle_t *sbh;
|
||||
|
||||
/* Trap exceptions in this thread so we don't take down the whole process */
|
||||
DosSetExceptionHandler( ®_rec );
|
||||
|
||||
rc = DosOpenQueue(&owner, &workq,
|
||||
apr_psprintf(pchild, "/queues/httpd/work.%d", getpid()));
|
||||
|
||||
if (rc) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
|
||||
"unable to open work queue, exiting");
|
||||
ap_scoreboard_image->servers[child_slot][thread_slot].tid = 0;
|
||||
}
|
||||
|
||||
conn_id = ID_FROM_CHILD_THREAD(child_slot, thread_slot);
|
||||
ap_update_child_status_from_indexes(child_slot, thread_slot, SERVER_READY,
|
||||
NULL);
|
||||
|
||||
apr_allocator_create(&allocator);
|
||||
apr_allocator_max_free_set(allocator, ap_max_mem_free);
|
||||
bucket_alloc = apr_bucket_alloc_create_ex(allocator);
|
||||
|
||||
while (rc = DosReadQueue(workq, &rd, &len, (PPVOID)&worker_args, 0, DCWW_WAIT, &priority, NULLHANDLE),
|
||||
rc == 0 && rd.ulData != WORKTYPE_EXIT) {
|
||||
pconn = worker_args->pconn;
|
||||
ap_create_sb_handle(&sbh, pconn, child_slot, thread_slot);
|
||||
current_conn = ap_run_create_connection(pconn, ap_server_conf,
|
||||
worker_args->conn_sd, conn_id,
|
||||
sbh, bucket_alloc);
|
||||
|
||||
if (current_conn) {
|
||||
ap_process_connection(current_conn, worker_args->conn_sd);
|
||||
ap_lingering_close(current_conn);
|
||||
}
|
||||
|
||||
apr_pool_destroy(pconn);
|
||||
ap_update_child_status_from_indexes(child_slot, thread_slot,
|
||||
SERVER_READY, NULL);
|
||||
}
|
||||
|
||||
ap_update_child_status_from_indexes(child_slot, thread_slot, SERVER_DEAD,
|
||||
NULL);
|
||||
|
||||
apr_bucket_alloc_destroy(bucket_alloc);
|
||||
apr_allocator_destroy(allocator);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void server_maintenance(void *vpArg)
|
||||
{
|
||||
int num_idle, num_needed;
|
||||
ULONG num_pending = 0;
|
||||
int threadnum;
|
||||
HQUEUE workq;
|
||||
ULONG rc;
|
||||
PID owner;
|
||||
|
||||
rc = DosOpenQueue(&owner, &workq,
|
||||
apr_psprintf(pchild, "/queues/httpd/work.%d", getpid()));
|
||||
|
||||
if (rc) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
|
||||
"unable to open work queue in maintenance thread");
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
for (num_idle=0, threadnum=0; threadnum < HARD_THREAD_LIMIT; threadnum++) {
|
||||
num_idle += ap_scoreboard_image->servers[child_slot][threadnum].status == SERVER_READY;
|
||||
}
|
||||
|
||||
DosQueryQueue(workq, &num_pending);
|
||||
num_needed = ap_min_spare_threads - num_idle + num_pending;
|
||||
|
||||
if (num_needed > 0) {
|
||||
for (threadnum=0; threadnum < num_needed; threadnum++) {
|
||||
add_worker();
|
||||
}
|
||||
}
|
||||
|
||||
if (num_idle - num_pending > ap_max_spare_threads) {
|
||||
DosWriteQueue(workq, WORKTYPE_EXIT, 0, NULL, 0);
|
||||
}
|
||||
} while (DosWaitEventSem(shutdown_event, 500) == ERROR_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Signal handling routines */
|
||||
|
||||
static void sig_term(int sig)
|
||||
{
|
||||
shutdown_pending = 1;
|
||||
is_graceful = 0;
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void sig_hup(int sig)
|
||||
{
|
||||
shutdown_pending = 1;
|
||||
is_graceful = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void set_signals()
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
sigemptyset(&sa.sa_mask);
|
||||
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)");
|
||||
|
||||
sa.sa_handler = sig_hup;
|
||||
|
||||
if (sigaction(SIGHUP, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
|
||||
}
|
||||
Reference in New Issue
Block a user