Blame modules/fcgid/fcgid_proc_win.c

Packit d68d13
/*
Packit d68d13
 * Licensed to the Apache Software Foundation (ASF) under one or more
Packit d68d13
 * contributor license agreements.  See the NOTICE file distributed with
Packit d68d13
 * this work for additional information regarding copyright ownership.
Packit d68d13
 * The ASF licenses this file to You under the Apache License, Version 2.0
Packit d68d13
 * (the "License"); you may not use this file except in compliance with
Packit d68d13
 * the License.  You may obtain a copy of the License at
Packit d68d13
 *
Packit d68d13
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit d68d13
 *
Packit d68d13
 * Unless required by applicable law or agreed to in writing, software
Packit d68d13
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit d68d13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit d68d13
 * See the License for the specific language governing permissions and
Packit d68d13
 * limitations under the License.
Packit d68d13
 */
Packit d68d13
Packit d68d13
Packit d68d13
#include "httpd.h"
Packit d68d13
#include "apr_thread_proc.h"
Packit d68d13
#include "apr_strings.h"
Packit d68d13
#include "apr_portable.h"
Packit d68d13
#include "apr_pools.h"
Packit d68d13
#include "util_script.h"
Packit d68d13
#include "mod_core.h"
Packit d68d13
#include "mod_cgi.h"
Packit d68d13
#include "apr_tables.h"
Packit d68d13
#include "fcgid_proc.h"
Packit d68d13
#include "fcgid_proctbl.h"
Packit d68d13
#include "fcgid_protocol.h"
Packit d68d13
#include "fcgid_conf.h"
Packit d68d13
#include "fcgid_pm.h"
Packit d68d13
#include "fcgid_spawn_ctl.h"
Packit d68d13
#define SHUTDOWN_EVENT_NAME "_FCGI_SHUTDOWN_EVENT_"
Packit d68d13
#define FINISH_EVENT_DATA_NAME "finish_event"
Packit d68d13
#ifndef SIGKILL
Packit d68d13
#define SIGKILL 9
Packit d68d13
#endif
Packit d68d13
Packit d68d13
/* It's tested on WinNT ONLY, if it work on the other MS platform, let me know */
Packit d68d13
#if WINVER < 0x0400
Packit d68d13
#error It is tested on WinNT only
Packit d68d13
#endif
Packit d68d13
Packit d68d13
typedef struct {
Packit d68d13
    HANDLE handle_pipe;
Packit d68d13
    OVERLAPPED overlap_read;
Packit d68d13
    OVERLAPPED overlap_write;
Packit d68d13
} fcgid_namedpipe_handle;
Packit d68d13
Packit d68d13
static int g_process_counter = 0;
Packit d68d13
Packit d68d13
static apr_status_t close_finish_event(void *finishevent)
Packit d68d13
{
Packit d68d13
    HANDLE *finish_event = finishevent;
Packit d68d13
Packit d68d13
    CloseHandle(*finish_event);
Packit d68d13
    return APR_SUCCESS;
Packit d68d13
}
Packit d68d13
Packit d68d13
apr_status_t proc_spawn_process(const char *cmdline, fcgid_proc_info *procinfo,
Packit d68d13
                                fcgid_procnode *procnode)
Packit d68d13
{
Packit d68d13
    HANDLE *finish_event, listen_handle;
Packit d68d13
    SECURITY_ATTRIBUTES SecurityAttributes;
Packit d68d13
    fcgid_server_conf *sconf;
Packit d68d13
    apr_procattr_t *proc_attr;
Packit d68d13
    apr_status_t rv;
Packit d68d13
    apr_file_t *file;
Packit d68d13
    const char * const *proc_environ;
Packit d68d13
    char sock_path[FCGID_PATH_MAX];
Packit d68d13
    const char **wargv;
Packit d68d13
Packit d68d13
    /* Build wrapper args */
Packit d68d13
    apr_tokenize_to_argv(cmdline, (char ***)&wargv, procnode->proc_pool);
Packit d68d13
Packit d68d13
    memset(&SecurityAttributes, 0, sizeof(SecurityAttributes));
Packit d68d13
Packit d68d13
    /* Prepare finish event */
Packit d68d13
    finish_event = apr_palloc(procnode->proc_pool, sizeof(HANDLE));
Packit d68d13
    *finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
Packit d68d13
    if (*finish_event == NULL
Packit d68d13
        || !SetHandleInformation(*finish_event, HANDLE_FLAG_INHERIT, TRUE))
Packit d68d13
    {
Packit d68d13
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
Packit d68d13
                     procinfo->main_server,
Packit d68d13
                     "mod_fcgid: can't create mutex for subprocess");
Packit d68d13
        return APR_ENOLOCK;
Packit d68d13
    }
Packit d68d13
    apr_pool_cleanup_register(procnode->proc_pool, finish_event,
Packit d68d13
                              close_finish_event, apr_pool_cleanup_null);
Packit d68d13
Packit d68d13
    /* For proc_kill_gracefully() */
Packit d68d13
    apr_pool_userdata_set(finish_event, FINISH_EVENT_DATA_NAME,
Packit d68d13
                          NULL, procnode->proc_pool);
Packit d68d13
Packit d68d13
    /* Pass the finish event id to subprocess */
Packit d68d13
    apr_table_setn(procinfo->proc_environ, SHUTDOWN_EVENT_NAME,
Packit d68d13
                   apr_ltoa(procnode->proc_pool, (long) *finish_event));
Packit d68d13
Packit d68d13
    /* Prepare the listen namedpipe file name (no check for truncation) */
Packit d68d13
    apr_snprintf(sock_path, sizeof sock_path,
Packit d68d13
                 "\\\\.\\pipe\\fcgidpipe-%lu.%d",
Packit d68d13
                 GetCurrentProcessId(), g_process_counter++);
Packit d68d13
Packit d68d13
    /* Prepare the listen namedpipe handle */
Packit d68d13
    SecurityAttributes.bInheritHandle = TRUE;
Packit d68d13
    SecurityAttributes.nLength = sizeof(SecurityAttributes);
Packit d68d13
    SecurityAttributes.lpSecurityDescriptor = NULL;
Packit d68d13
    listen_handle = CreateNamedPipe(sock_path,
Packit d68d13
                                    PIPE_ACCESS_DUPLEX,
Packit d68d13
                                    PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
Packit d68d13
                                    PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
Packit d68d13
                                    8192, 8192, 0, &SecurityAttributes);
Packit d68d13
    if (listen_handle == INVALID_HANDLE_VALUE) {
Packit d68d13
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
Packit d68d13
                     procinfo->main_server,
Packit d68d13
                     "mod_fcgid: can't create namedpipe for subprocess");
Packit d68d13
        return APR_ENOSOCKET;
Packit d68d13
    }
Packit d68d13
    apr_cpystrn(procnode->socket_path, sock_path, sizeof(procnode->socket_path));
Packit d68d13
    apr_cpystrn(procnode->executable_path, wargv[0],
Packit d68d13
                sizeof(procnode->executable_path));
Packit d68d13
Packit d68d13
    /* Build environment variables */
Packit d68d13
    proc_environ = (const char * const *)
Packit d68d13
                   ap_create_environment(procnode->proc_pool,
Packit d68d13
                                         procinfo->proc_environ);
Packit d68d13
    if (!proc_environ) {
Packit d68d13
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
Packit d68d13
                     procinfo->main_server,
Packit d68d13
                     "mod_fcgid: can't build environment variables");
Packit d68d13
        return APR_ENOMEM;
Packit d68d13
    }
Packit d68d13
Packit d68d13
    /* Create process now */
Packit d68d13
    if ((rv = apr_procattr_create(&proc_attr, procnode->proc_pool))
Packit d68d13
               != APR_SUCCESS
Packit d68d13
        || (rv = apr_procattr_dir_set(proc_attr,
Packit d68d13
                     ap_make_dirstr_parent(procnode->proc_pool,
Packit d68d13
                                           wargv[0]))) != APR_SUCCESS
Packit d68d13
        || (rv = apr_procattr_cmdtype_set(proc_attr, APR_PROGRAM))
Packit d68d13
               != APR_SUCCESS
Packit d68d13
        || (rv = apr_procattr_detach_set(proc_attr, 1)) != APR_SUCCESS
Packit d68d13
        || (rv = apr_procattr_io_set(proc_attr, APR_NO_PIPE,
Packit d68d13
                                     APR_NO_FILE, APR_NO_FILE)) != APR_SUCCESS
Packit d68d13
        || (rv = apr_os_file_put(&file, &listen_handle, 0,
Packit d68d13
                                 procnode->proc_pool)) != APR_SUCCESS
Packit d68d13
        || (rv = apr_procattr_child_in_set(proc_attr, file, NULL))
Packit d68d13
               != APR_SUCCESS)
Packit d68d13
    {
Packit d68d13
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, procinfo->main_server,
Packit d68d13
                     "mod_fcgid: can't create FastCGI process attribute");
Packit d68d13
        CloseHandle(listen_handle);
Packit d68d13
        return APR_ENOPROC;
Packit d68d13
    }
Packit d68d13
Packit d68d13
    /* fork and exec now */
Packit d68d13
    rv = apr_proc_create(&(procnode->proc_id), wargv[0], wargv,
Packit d68d13
                         proc_environ,
Packit d68d13
                         proc_attr, procnode->proc_pool);
Packit d68d13
Packit d68d13
    /* OK, I created the process, now put it back to idle list */
Packit d68d13
    CloseHandle(listen_handle);
Packit d68d13
Packit d68d13
    if (rv != APR_SUCCESS) {
Packit d68d13
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, procinfo->main_server,
Packit d68d13
                     "mod_fcgid: can't run %s", wargv[0]);
Packit d68d13
        return rv;
Packit d68d13
    }
Packit d68d13
Packit d68d13
    /* FcgidWin32PreventOrphans feature */
Packit d68d13
    sconf = ap_get_module_config(procinfo->main_server->module_config,
Packit d68d13
                                 &fcgid_module);
Packit d68d13
Packit d68d13
    if (sconf->hJobObjectForAutoCleanup != NULL) {
Packit d68d13
        /* Associate cgi process to current process */
Packit d68d13
        if (AssignProcessToJobObject(sconf->hJobObjectForAutoCleanup,
Packit d68d13
                                     procnode->proc_id.hproc) == 0) {
Packit d68d13
            ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
Packit d68d13
                         procinfo->main_server,
Packit d68d13
                         "mod_fcgid: unable to assign child process to "
Packit d68d13
                         "job object");
Packit d68d13
        }
Packit d68d13
    }
Packit d68d13
Packit d68d13
    return APR_SUCCESS;
Packit d68d13
}
Packit d68d13
Packit d68d13
apr_status_t proc_kill_gracefully(fcgid_procnode *procnode,
Packit d68d13
                                  server_rec *main_server)
Packit d68d13
{
Packit d68d13
    HANDLE *finish_event = NULL;
Packit d68d13
Packit d68d13
    apr_pool_userdata_get((void **) &finish_event,
Packit d68d13
                          FINISH_EVENT_DATA_NAME, procnode->proc_pool);
Packit d68d13
Packit d68d13
    if (finish_event != NULL)
Packit d68d13
        SetEvent(*finish_event);
Packit d68d13
    return APR_SUCCESS;
Packit d68d13
}
Packit d68d13
Packit d68d13
apr_status_t proc_kill_force(fcgid_procnode *procnode,
Packit d68d13
                             server_rec *main_server)
Packit d68d13
{
Packit d68d13
    return apr_proc_kill(&(procnode->proc_id), SIGKILL);
Packit d68d13
}
Packit d68d13
Packit d68d13
apr_status_t proc_wait_process(server_rec *main_server,
Packit d68d13
                               fcgid_procnode *procnode)
Packit d68d13
{
Packit d68d13
    apr_status_t rv;
Packit d68d13
    int exitcode;
Packit d68d13
    apr_exit_why_e exitwhy;
Packit d68d13
Packit d68d13
    if ((rv = apr_proc_wait(&(procnode->proc_id), &exitcode, &exitwhy,
Packit d68d13
                            APR_NOWAIT)) == APR_CHILD_DONE) {
Packit d68d13
        /* Log why and how it die */
Packit d68d13
        proc_print_exit_info(procnode, exitcode, exitwhy, main_server);
Packit d68d13
Packit d68d13
        /* Register the death */
Packit d68d13
        register_termination(main_server, procnode);
Packit d68d13
Packit d68d13
        /* Destroy pool */
Packit d68d13
        apr_pool_destroy(procnode->proc_pool);
Packit d68d13
        procnode->proc_pool = NULL;
Packit d68d13
    }
Packit d68d13
Packit d68d13
    return rv;
Packit d68d13
}
Packit d68d13
Packit d68d13
static apr_status_t ipc_handle_cleanup(void *thehandle)
Packit d68d13
{
Packit d68d13
    fcgid_namedpipe_handle *handle = thehandle;
Packit d68d13
Packit d68d13
    /* Sanity check */
Packit d68d13
    if (handle) {
Packit d68d13
        if (handle->handle_pipe != INVALID_HANDLE_VALUE)
Packit d68d13
            CloseHandle(handle->handle_pipe);
Packit d68d13
        if (handle->overlap_read.hEvent != NULL)
Packit d68d13
            CloseHandle(handle->overlap_read.hEvent);
Packit d68d13
        if (handle->overlap_write.hEvent != NULL)
Packit d68d13
            CloseHandle(handle->overlap_write.hEvent);
Packit d68d13
        handle->handle_pipe = INVALID_HANDLE_VALUE;
Packit d68d13
        handle->overlap_read.hEvent = NULL;
Packit d68d13
        handle->overlap_write.hEvent = NULL;
Packit d68d13
    }
Packit d68d13
Packit d68d13
    return APR_SUCCESS;
Packit d68d13
}
Packit d68d13
Packit d68d13
apr_status_t proc_connect_ipc(fcgid_procnode *procnode, fcgid_ipc *ipc_handle)
Packit d68d13
{
Packit d68d13
    /* Prepare the ipc struct */
Packit d68d13
    fcgid_namedpipe_handle *handle_info;
Packit d68d13
Packit d68d13
    ipc_handle->ipc_handle_info =
Packit d68d13
        (fcgid_namedpipe_handle *) apr_pcalloc(ipc_handle->request->pool,
Packit d68d13
                                               sizeof
Packit d68d13
                                               (fcgid_namedpipe_handle));
Packit d68d13
    handle_info = (fcgid_namedpipe_handle *) ipc_handle->ipc_handle_info;
Packit d68d13
Packit d68d13
    /* Prepare OVERLAPPED struct for non-block I/O */
Packit d68d13
    handle_info->overlap_read.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
Packit d68d13
    handle_info->overlap_write.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
Packit d68d13
    handle_info->handle_pipe = INVALID_HANDLE_VALUE;
Packit d68d13
Packit d68d13
    apr_pool_cleanup_register(ipc_handle->request->pool,
Packit d68d13
                              handle_info,
Packit d68d13
                              ipc_handle_cleanup, apr_pool_cleanup_null);
Packit d68d13
Packit d68d13
    if (handle_info->overlap_read.hEvent == NULL
Packit d68d13
            || handle_info->overlap_write.hEvent == NULL)
Packit d68d13
        return APR_ENOMEM;
Packit d68d13
Packit d68d13
    /* Connect to name pipe */
Packit d68d13
    handle_info->handle_pipe = CreateFile(procnode->socket_path,
Packit d68d13
                                          GENERIC_READ | GENERIC_WRITE,
Packit d68d13
                                          0, NULL, OPEN_EXISTING,
Packit d68d13
                                          FILE_FLAG_OVERLAPPED, NULL);
Packit d68d13
Packit d68d13
    if (handle_info->handle_pipe == INVALID_HANDLE_VALUE
Packit d68d13
        && ipc_handle->connect_timeout != 0
Packit d68d13
        && GetLastError() == ERROR_PIPE_BUSY)
Packit d68d13
    {
Packit d68d13
        /* XXX - there appears to be a race, here
Packit d68d13
         * Wait for pipe to be ready for connect, and try again
Packit d68d13
         */
Packit d68d13
        if (WaitNamedPipe(procnode->socket_path, ipc_handle->connect_timeout))
Packit d68d13
        {
Packit d68d13
            handle_info->handle_pipe = CreateFile(procnode->socket_path,
Packit d68d13
                                                  GENERIC_READ | GENERIC_WRITE,
Packit d68d13
                                                  0, NULL, OPEN_EXISTING,
Packit d68d13
                                                  FILE_FLAG_OVERLAPPED, NULL);
Packit d68d13
        }
Packit d68d13
    }
Packit d68d13
Packit d68d13
    if (handle_info->handle_pipe == INVALID_HANDLE_VALUE)
Packit d68d13
    {
Packit d68d13
        if (GetLastError() == ERROR_FILE_NOT_FOUND) /* The process has exited */
Packit d68d13
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ipc_handle->request,
Packit d68d13
                          "mod_fcgid: can't connect to named pipe, FastCGI"
Packit d68d13
                          " server %" APR_PID_T_FMT " has been terminated",
Packit d68d13
                          procnode->proc_id.pid);
Packit d68d13
        else
Packit d68d13
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, apr_get_os_error(),
Packit d68d13
                          ipc_handle->request,
Packit d68d13
                          "mod_fcgid: can't connect to named pipe, FastCGI"
Packit d68d13
                          " server pid %" APR_PID_T_FMT,
Packit d68d13
                          procnode->proc_id.pid);
Packit d68d13
        return APR_ESPIPE;
Packit d68d13
    }
Packit d68d13
Packit d68d13
    /* Now named pipe connected */
Packit d68d13
    return APR_SUCCESS;
Packit d68d13
}
Packit d68d13
Packit d68d13
apr_status_t proc_close_ipc(fcgid_ipc * ipc_handle)
Packit d68d13
{
Packit d68d13
    apr_status_t rv;
Packit d68d13
Packit d68d13
    rv = apr_pool_cleanup_run(ipc_handle->request->pool,
Packit d68d13
                              ipc_handle->ipc_handle_info,
Packit d68d13
                              ipc_handle_cleanup);
Packit d68d13
    ipc_handle->ipc_handle_info = NULL;
Packit d68d13
    return rv;
Packit d68d13
}
Packit d68d13
Packit d68d13
apr_status_t proc_read_ipc(fcgid_ipc * ipc_handle, const char *buffer,
Packit d68d13
                           apr_size_t * size)
Packit d68d13
{
Packit d68d13
    apr_status_t rv;
Packit d68d13
    fcgid_namedpipe_handle *handle_info;
Packit d68d13
    DWORD bytesread;
Packit d68d13
Packit d68d13
    handle_info = (fcgid_namedpipe_handle *) ipc_handle->ipc_handle_info;
Packit d68d13
Packit d68d13
    if (ReadFile(handle_info->handle_pipe, (LPVOID) buffer,
Packit d68d13
                 *size, &bytesread, &handle_info->overlap_read)) {
Packit d68d13
        *size = bytesread;
Packit d68d13
        return APR_SUCCESS;
Packit d68d13
    } else if ((rv = GetLastError()) != ERROR_IO_PENDING) {
Packit d68d13
        ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_FROM_OS_ERROR(rv),
Packit d68d13
                      ipc_handle->request,
Packit d68d13
                      "mod_fcgid: can't read from pipe");
Packit d68d13
        return rv;
Packit d68d13
    } else {
Packit d68d13
        /* it's ERROR_IO_PENDING */
Packit d68d13
        DWORD transferred;
Packit d68d13
        DWORD dwWaitResult
Packit d68d13
            = WaitForSingleObject(handle_info->overlap_read.hEvent,
Packit d68d13
                                  ipc_handle->communation_timeout * 1000);
Packit d68d13
Packit d68d13
        if (dwWaitResult == WAIT_OBJECT_0) {
Packit d68d13
            if (!GetOverlappedResult(handle_info->handle_pipe,
Packit d68d13
                                     &handle_info->overlap_read,
Packit d68d13
                                     &transferred, FALSE /* don't wait */ )
Packit d68d13
                || transferred == 0) {
Packit d68d13
                rv = apr_get_os_error();
Packit d68d13
                ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv,
Packit d68d13
                              ipc_handle->request,
Packit d68d13
                              "mod_fcgid: get overlap result error");
Packit d68d13
                return rv;
Packit d68d13
            }
Packit d68d13
Packit d68d13
            *size = transferred;
Packit d68d13
            return APR_SUCCESS;
Packit d68d13
        } else {
Packit d68d13
            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, ipc_handle->request,
Packit d68d13
                          "mod_fcgid: read timeout from pipe");
Packit d68d13
            return APR_ETIMEDOUT;
Packit d68d13
        }
Packit d68d13
    }
Packit d68d13
}
Packit d68d13
Packit d68d13
apr_status_t proc_write_ipc(fcgid_ipc * ipc_handle,
Packit d68d13
                            apr_bucket_brigade * birgade_send)
Packit d68d13
{
Packit d68d13
    fcgid_namedpipe_handle *handle_info;
Packit d68d13
    apr_bucket *bucket_request;
Packit d68d13
    apr_status_t rv;
Packit d68d13
    DWORD transferred;
Packit d68d13
Packit d68d13
    handle_info = (fcgid_namedpipe_handle *) ipc_handle->ipc_handle_info;
Packit d68d13
Packit d68d13
    for (bucket_request = APR_BRIGADE_FIRST(birgade_send);
Packit d68d13
         bucket_request != APR_BRIGADE_SENTINEL(birgade_send);
Packit d68d13
         bucket_request = APR_BUCKET_NEXT(bucket_request))
Packit d68d13
    {
Packit d68d13
        const char *write_buf;
Packit d68d13
        apr_size_t write_buf_len;
Packit d68d13
        apr_size_t has_write;
Packit d68d13
Packit d68d13
        if (APR_BUCKET_IS_METADATA(bucket_request))
Packit d68d13
            continue;
Packit d68d13
Packit d68d13
        if ((rv = apr_bucket_read(bucket_request, &write_buf, &write_buf_len,
Packit d68d13
                                  APR_BLOCK_READ)) != APR_SUCCESS) {
Packit d68d13
            ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, ipc_handle->request,
Packit d68d13
                          "mod_fcgid: can't read request from bucket");
Packit d68d13
            return rv;
Packit d68d13
        }
Packit d68d13
Packit d68d13
        /* Write the buffer to fastcgi server */
Packit d68d13
        has_write = 0;
Packit d68d13
        while (has_write < write_buf_len) {
Packit d68d13
            DWORD byteswrite;
Packit d68d13
Packit d68d13
            if (WriteFile(handle_info->handle_pipe,
Packit d68d13
                          write_buf + has_write,
Packit d68d13
                          write_buf_len - has_write,
Packit d68d13
                          &byteswrite, &handle_info->overlap_write)) {
Packit d68d13
                has_write += byteswrite;
Packit d68d13
                continue;
Packit d68d13
            } else if ((rv = GetLastError()) != ERROR_IO_PENDING) {
Packit d68d13
                ap_log_rerror(APLOG_MARK, APLOG_WARNING,
Packit d68d13
                              APR_FROM_OS_ERROR(rv), ipc_handle->request,
Packit d68d13
                              "mod_fcgid: can't write to pipe");
Packit d68d13
                return rv;
Packit d68d13
            } else {
Packit d68d13
                /*
Packit d68d13
                   it's ERROR_IO_PENDING on write
Packit d68d13
                 */
Packit d68d13
                DWORD dwWaitResult =
Packit d68d13
                    WaitForSingleObject(handle_info->overlap_write.hEvent,
Packit d68d13
                                        ipc_handle->communation_timeout * 1000);
Packit d68d13
                if (dwWaitResult == WAIT_OBJECT_0) {
Packit d68d13
                    if (!GetOverlappedResult(handle_info->handle_pipe,
Packit d68d13
                                             &handle_info->overlap_write,
Packit d68d13
                                             &transferred,
Packit d68d13
                                             FALSE /* don't wait */ )
Packit d68d13
                        || transferred == 0)
Packit d68d13
                    {
Packit d68d13
                        ap_log_rerror(APLOG_MARK, APLOG_WARNING,
Packit d68d13
                                      apr_get_os_error(), ipc_handle->request,
Packit d68d13
                                      "mod_fcgid: get overlap result error");
Packit d68d13
                        return APR_ESPIPE;
Packit d68d13
                    }
Packit d68d13
                    has_write += transferred;
Packit d68d13
                    continue;
Packit d68d13
                } else {
Packit d68d13
                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0,
Packit d68d13
                                  ipc_handle->request,
Packit d68d13
                                  "mod_fcgid: write timeout to pipe");
Packit d68d13
                    return APR_ESPIPE;
Packit d68d13
                }
Packit d68d13
            }
Packit d68d13
        }
Packit d68d13
    }
Packit d68d13
Packit d68d13
    return APR_SUCCESS;
Packit d68d13
}
Packit d68d13
Packit d68d13
void proc_print_exit_info(fcgid_procnode * procnode, int exitcode,
Packit d68d13
                          apr_exit_why_e exitwhy, server_rec * main_server)
Packit d68d13
{
Packit d68d13
    char *diewhy = NULL;
Packit d68d13
Packit d68d13
    /* Reasons to exit */
Packit d68d13
    switch (procnode->diewhy) {
Packit d68d13
    case FCGID_DIE_KILLSELF:
Packit d68d13
        if (exitwhy == APR_PROC_EXIT)
Packit d68d13
            diewhy = "normal exit";
Packit d68d13
        else
Packit d68d13
            diewhy = "access violation";
Packit d68d13
        break;
Packit d68d13
    case FCGID_DIE_IDLE_TIMEOUT:
Packit d68d13
        diewhy = "idle timeout";
Packit d68d13
        break;
Packit d68d13
    case FCGID_DIE_LIFETIME_EXPIRED:
Packit d68d13
        diewhy = "lifetime expired";
Packit d68d13
        break;
Packit d68d13
    case FCGID_DIE_BUSY_TIMEOUT:
Packit d68d13
        diewhy = "busy timeout";
Packit d68d13
        break;
Packit d68d13
    case FCGID_DIE_CONNECT_ERROR:
Packit d68d13
        diewhy = "connect error, server may has exited";
Packit d68d13
        break;
Packit d68d13
    case FCGID_DIE_COMM_ERROR:
Packit d68d13
        diewhy = "communication error";
Packit d68d13
        break;
Packit d68d13
    case FCGID_DIE_SHUTDOWN:
Packit d68d13
        diewhy = "shutting down";
Packit d68d13
        break;
Packit d68d13
    default:
Packit d68d13
        diewhy = "unknown";
Packit d68d13
    }
Packit d68d13
Packit d68d13
    /* Print log now */
Packit d68d13
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, main_server,
Packit d68d13
                     "mod_fcgid: process %s(%" APR_PID_T_FMT ") exit(%s), return code %d",
Packit d68d13
                     procnode->executable_path, procnode->proc_id.pid, diewhy, exitcode);
Packit d68d13
}