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