Apache HTTPD
mpmt_os2_child.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define INCL_NOPMAPI
18#define INCL_DOS
19#define INCL_DOSERRORS
20
21#include "ap_config.h"
22#include "httpd.h"
23#include "mpm_default.h"
24#include "http_main.h"
25#include "http_log.h"
26#include "http_config.h"
27#include "http_core.h" /* for get_remote_host */
28#include "http_connection.h"
29#include "scoreboard.h"
30#include "ap_mpm.h"
31#include "ap_listen.h"
32#include "apr_portable.h"
33#include "apr_poll.h"
34#include "mpm_common.h"
35#include "apr_strings.h"
36#include <os2.h>
37#include <process.h>
38
40
41/* XXXXXX move these to header file private to this MPM */
42
43/* We don't need many processes,
44 * they're only for redundancy in the event of a crash
45 */
46#define HARD_SERVER_LIMIT 10
47
48/* Limit on the total number of threads per process
49 */
50#ifndef HARD_THREAD_LIMIT
51#define HARD_THREAD_LIMIT 256
52#endif
53
54#define ID_FROM_CHILD_THREAD(c, t) ((c * HARD_THREAD_LIMIT) + t)
55
60
61#define WORKTYPE_CONN 0
62#define WORKTYPE_EXIT 1
63
65static int child_slot;
66static int shutdown_pending = 0;
67extern int ap_my_generation;
68static int volatile is_graceful = 1;
69HEV shutdown_event; /* signaled when this child is shutting down */
70
71/* grab some MPM globals */
72extern int ap_min_spare_threads;
73extern int ap_max_spare_threads;
75
76static void worker_main(void *vpArg);
77static void clean_child_exit(int code);
78static void set_signals();
79static void server_maintenance(void *vpArg);
80
81
82static void clean_child_exit(int code)
83{
84 if (pchild) {
86 }
87
88 exit(code);
89}
90
91
92
94{
96 int requests_this_child = 0;
97 int rv = 0;
98 unsigned long ulTimes;
99 int my_pid = getpid();
100 ULONG rc, c;
103 int num_listeners;
105 void *sb_mem;
106
107 /* Stop Ctrl-C/Ctrl-Break signals going to child processes */
109 set_signals();
110
111 /* Create pool for child */
113 apr_pool_tag(pchild, "pchild");
114
116
117 /* Create an event semaphore used to trigger other threads to shutdown */
119
120 if (rc) {
122 "unable to create shutdown semaphore, exiting");
124 }
125
126 /* Gain access to the scoreboard. */
129
130 if (rc) {
132 "scoreboard not readable in child, exiting");
134 }
135
138
139 /* Gain access to the accpet mutex */
141
142 if (rc) {
144 "accept mutex couldn't be accessed in child, exiting");
146 }
147
148 /* Find our pid in the scoreboard so we know what slot our parent allocated us */
150
153 "child pid not found in scoreboard, exiting");
155 }
156
159
160 /* Set up an OS/2 queue for passing connections & termination requests
161 * to worker threads
162 */
163 rc = DosCreateQueue(&workq, QUE_FIFO, apr_psprintf(pchild, "/queues/httpd/work.%d", my_pid));
164
165 if (rc) {
167 "unable to create work queue, exiting");
169 }
170
171 /* Create initial pool of worker threads */
172 for (c = 0; c < ap_min_spare_threads; c++) {
173// ap_scoreboard_image->servers[child_slot][c].tid = _beginthread(worker_main, NULL, 128*1024, (void *)c);
174 }
175
176 /* Start maintenance thread */
178
179 /* Set up poll */
180 for (num_listeners = 0, lr = ap_listeners; lr; lr = lr->next) {
182 }
183
185
186 for (lr = ap_listeners; lr != NULL; lr = lr->next) {
187 apr_pollfd_t pfd = { 0 };
188
190 pfd.desc.s = lr->sd;
191 pfd.reqevents = APR_POLLIN;
192 pfd.client_data = lr;
194 }
195
196 /* Main connection accept loop */
197 do {
198 apr_pool_t *pconn;
200 int last_poll_idx = 0;
201
202 apr_pool_create(&pconn, pchild);
203 apr_pool_tag(pconn, "transaction");
204 worker_args = apr_palloc(pconn, sizeof(worker_args_t));
205 worker_args->pconn = pconn;
206
207 if (num_listeners == 1) {
208 rv = apr_socket_accept(&worker_args->conn_sd, ap_listeners->sd, pconn);
209 } else {
212
214
215 if (shutdown_pending) {
217 break;
218 }
219
220 rv = APR_FROM_OS_ERROR(rc);
221
222 if (rv == APR_SUCCESS) {
225 }
226
227 if (rv == APR_SUCCESS) {
229 last_poll_idx = 0;
230 }
231
232 lr = poll_results[last_poll_idx++].client_data;
233 rv = apr_socket_accept(&worker_args->conn_sd, lr->sd, pconn);
235 }
236 }
237
238 if (rv != APR_SUCCESS) {
239 if (!APR_STATUS_IS_EINTR(rv)) {
241 "apr_socket_accept");
243 }
244 } else {
247 }
248
250 break;
252
256
257 if (is_graceful) {
258 char someleft;
259
260 /* tell our worker threads to exit */
261 for (c=0; c<HARD_THREAD_LIMIT; c++) {
264 }
265 }
266
267 do {
268 someleft = 0;
269
270 for (c=0; c<HARD_THREAD_LIMIT; c++) {
272 someleft = 1;
273 DosSleep(1000);
274 break;
275 }
276 }
277 } while (someleft);
278 } else {
280
281 for (c=0; c<HARD_THREAD_LIMIT; c++) {
284 }
285 }
286 }
287
289}
290
291
292
294{
295 int thread_slot;
296 int stacksize = ap_thread_stacksize == 0 ? 128*1024 : ap_thread_stacksize;
297
298 /* Find a free thread slot */
303 _beginthread(worker_main, NULL, stacksize, (void *)thread_slot);
304 break;
305 }
306 }
307}
308
309
310
313 CONTEXTRECORD *pContext,
314 PVOID p)
315{
316 int c;
317
318 if (pReportRec->fHandlerFlags & EH_NESTED_CALL) {
320 }
321
322 if (pReportRec->ExceptionNum == XCPT_ACCESS_VIOLATION ||
323 pReportRec->ExceptionNum == XCPT_INTEGER_DIVIDE_BY_ZERO) {
325 "caught exception in worker thread, initiating child shutdown pid=%d", getpid());
326 for (c=0; c<HARD_THREAD_LIMIT; c++) {
329 break;
330 }
331 }
332
333 /* Shut down process ASAP, it could be quite unhealthy & leaking resources */
336 kill(getpid(), SIGHUP);
338 }
339
341}
342
343
344
345static void worker_main(void *vpArg)
346{
349 long conn_id;
351 apr_pool_t *pconn;
353 apr_bucket_alloc_t *bucket_alloc;
356 PID owner;
357 int rc;
359 ULONG len;
360 BYTE priority;
361 int thread_slot = (int)vpArg;
363 ap_sb_handle_t *sbh;
364
365 /* Trap exceptions in this thread so we don't take down the whole process */
367
370
371 rc = DosOpenQueue(&owner, &workq,
372 apr_psprintf(pchild, "/queues/httpd/work.%d", getpid()));
373
374 if (rc) {
376 "unable to open work queue, exiting");
378 }
379
382 NULL);
383
387
388 while (rc = DosReadQueue(workq, &rd, &len, (PPVOID)&worker_args, 0, DCWW_WAIT, &priority, NULLHANDLE),
389 rc == 0 && rd.ulData != WORKTYPE_EXIT) {
390 pconn = worker_args->pconn;
393 worker_args->conn_sd, conn_id,
394 sbh, bucket_alloc);
395
396 if (current_conn) {
397 current_conn->current_thread = thd;
400 }
401
402 apr_pool_destroy(pconn);
405 }
406
408 NULL);
409
410 apr_bucket_alloc_destroy(bucket_alloc);
412}
413
414
415
416static void server_maintenance(void *vpArg)
417{
418 int num_idle, num_needed;
419 ULONG num_pending = 0;
420 int threadnum;
422 ULONG rc;
423 PID owner;
424
425 rc = DosOpenQueue(&owner, &workq,
426 apr_psprintf(pchild, "/queues/httpd/work.%d", getpid()));
427
428 if (rc) {
430 "unable to open work queue in maintenance thread");
431 return;
432 }
433
434 do {
437 }
438
441
442 if (num_needed > 0) {
444 add_worker();
445 }
446 }
447
450 }
452}
453
454
455
456/* Signal handling routines */
457
458static void sig_term(int sig)
459{
461 is_graceful = 0;
463}
464
465
466
467static void sig_hup(int sig)
468{
470 is_graceful = 1;
471}
472
473
474
475static void set_signals()
476{
477 struct sigaction sa;
478
479 sigemptyset(&sa.sa_mask);
480 sa.sa_flags = 0;
481 sa.sa_handler = sig_term;
482
483 if (sigaction(SIGTERM, &sa, NULL) < 0)
484 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00198) "sigaction(SIGTERM)");
485
486 sa.sa_handler = sig_hup;
487
488 if (sigaction(SIGHUP, &sa, NULL) < 0)
489 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00199) "sigaction(SIGHUP)");
490}
Symbol export macros and hook functions.
Apache Listeners Library.
Apache Multi-Processing Module library.
const char apr_size_t len
Definition ap_regex.h:187
#define FALSE
Definition abts.h:35
#define _beginthread(fn, d, pv)
APR Poll interface.
APR Portability Routines.
APR Strings library.
void ap_process_connection(conn_rec *c, void *csd)
Definition connection.c:210
void ap_lingering_close(conn_rec *c)
Definition connection.c:149
conn_rec * ap_run_create_connection(apr_pool_t *p, server_rec *server, apr_socket_t *csd, long conn_id, void *sbh, apr_bucket_alloc_t *alloc)
Definition connection.c:41
static apr_pool_t * pconf
Definition event.c:441
#define APLOG_USE_MODULE(foo)
void ap_run_child_init(apr_pool_t *pchild, server_rec *s)
Definition config.c:167
#define APEXIT_CHILDFATAL
Definition httpd.h:341
ap_listen_rec * ap_listeners
Definition listen.c:42
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_ERR
Definition http_log.h:67
#define ap_log_error
Definition http_log.h:370
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_WARNING
Definition http_log.h:68
server_rec * ap_server_conf
Definition config.c:62
DWORD my_pid
int ap_max_requests_per_child
Definition mpm_common.c:151
apr_size_t ap_thread_stacksize
Definition mpm_common.c:156
apr_uint32_t ap_max_mem_free
Definition mpm_common.c:155
#define APR_STATUS_IS_EINTR(s)
Definition apr_errno.h:1281
apr_redis_t * rc
Definition apr_redis.h:173
apr_size_t size
#define APR_FROM_OS_ERROR(e)
Definition apr_errno.h:1214
#define APR_SUCCESS
Definition apr_errno.h:225
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_sockaddr_t * sa
@ APR_POLL_SOCKET
Definition apr_poll.h:93
apr_abortfunc_t apr_allocator_t * allocator
Definition apr_pools.h:208
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
int sig
#define APR_POLLIN
Definition apr_poll.h:49
Apache Configuration.
Apache connection library.
CORE HTTP Daemon.
Apache Logging library.
Command line options.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
#define BYTE
return NULL
Definition mod_so.c:359
Multi-Processing Modules functions.
static void sig_term(int sig)
static void server_maintenance(void *vpArg)
static apr_pool_t * pchild
#define HARD_SERVER_LIMIT
int ap_max_spare_threads
Definition mpmt_os2.c:79
int ap_min_spare_threads
Definition mpmt_os2.c:78
static void sig_hup(int sig)
ULONG APIENTRY thread_exception_handler(EXCEPTIONREPORTRECORD *pReportRec, EXCEPTIONREGISTRATIONRECORD *pRegRec, CONTEXTRECORD *pContext, PVOID p)
#define WORKTYPE_CONN
static int shutdown_pending
int ap_my_generation
Definition mpmt_os2.c:88
HEV shutdown_event
HMTX ap_mpm_accept_mutex
Definition mpmt_os2.c:90
void ap_mpm_child_main(apr_pool_t *pconf)
static void clean_child_exit(int code)
#define ID_FROM_CHILD_THREAD(c, t)
static int volatile is_graceful
#define WORKTYPE_EXIT
#define HARD_THREAD_LIMIT
static void set_signals()
void add_worker()
static int child_slot
static void worker_main(void *vpArg)
apr_os_thread_t apr_os_thread_current()
Definition thread.c:142
static int requests_this_child
Definition prefork.c:380
Apache scoreboard library.
void ap_create_sb_handle(ap_sb_handle_t **new_sbh, apr_pool_t *p, int child_num, int thread_num)
Definition scoreboard.c:432
#define SERVER_STARTING
Definition scoreboard.h:57
scoreboard * ap_scoreboard_image
Definition scoreboard.c:44
const char * ap_scoreboard_fname
Definition scoreboard.c:45
void ap_init_scoreboard(void *shared_score)
Definition scoreboard.c:150
#define SERVER_DEAD
Definition scoreboard.h:56
int ap_calc_scoreboard_size(void)
Definition scoreboard.c:138
int ap_update_child_status_from_indexes(int child_num, int thread_num, int status, request_rec *r)
Definition scoreboard.c:575
#define SERVER_READY
Definition scoreboard.h:58
Apache's listeners record.
Definition ap_listen.h:47
ap_listen_rec * next
Definition ap_listen.h:51
apr_socket_t * sd
Definition ap_listen.h:55
void * client_data
Definition apr_poll.h:114
apr_int16_t reqevents
Definition apr_poll.h:111
apr_datatype_e desc_type
Definition apr_poll.h:110
apr_descriptor desc
Definition apr_poll.h:113
Structure to store things which are per connection.
Definition httpd.h:1152
ap_generation_t running_generation
Definition scoreboard.h:126
ap_generation_t generation
Definition scoreboard.h:139
worker_score ** servers
Definition scoreboard.h:163
process_score * parent
Definition scoreboard.h:162
global_score * global
Definition scoreboard.h:161
apr_pool_t * pconn
apr_socket_t * conn_sd
unsigned char status
Definition scoreboard.h:102
static apr_pollset_t * pollset
Definition testpoll.c:41
apr_socket_t * s
Definition apr_poll.h:101
apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock, apr_pool_t *connection_context)
Definition sockets.c:247
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray
Worker MPM defaults.