📄 mpmt_os2_child.c
字号:
}
if (rv != APR_SUCCESS) {
if (!APR_STATUS_IS_EINTR(rv)) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
"apr_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)");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -