summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorAllan K. Edwards <ake@apache.org>2003-03-04 23:15:51 +0100
committerAllan K. Edwards <ake@apache.org>2003-03-04 23:15:51 +0100
commit5a8d4863418f4123923797feb8b0ec730b98f4c2 (patch)
treebd6c746a341b88deda39af7272ea8d31c8fd9c17 /server
parentFix validation issue (added missing XML declaration). (diff)
downloadapache2-5a8d4863418f4123923797feb8b0ec730b98f4c2.tar.xz
apache2-5a8d4863418f4123923797feb8b0ec730b98f4c2.zip
Added the WindowsSocketsWorkaroud directive for Windows NT/2000/XP
to work around problems with certain VPN and Firewall products that have buggy AcceptEx implementations git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@98890 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server')
-rw-r--r--server/mpm/winnt/child.c46
-rw-r--r--server/mpm/winnt/mpm_winnt.c22
-rw-r--r--server/mpm/winnt/mpm_winnt.h1
3 files changed, 58 insertions, 11 deletions
diff --git a/server/mpm/winnt/child.c b/server/mpm/winnt/child.c
index 5ca5f7ca4f..95cabeed02 100644
--- a/server/mpm/winnt/child.c
+++ b/server/mpm/winnt/child.c
@@ -498,7 +498,7 @@ static void winnt_accept(void *lr_)
PCOMP_CONTEXT context = NULL;
DWORD BytesRead;
SOCKET nlsd;
- int rv;
+ int rv, err_count = 0;
apr_os_sock_get(&nlsd, lr->sd);
@@ -538,15 +538,38 @@ static void winnt_accept(void *lr_)
rv = apr_get_netos_error();
if ((rv == APR_FROM_OS_ERROR(WSAEINVAL)) ||
(rv == APR_FROM_OS_ERROR(WSAENOTSOCK))) {
- /* Hack alert. Occasionally, TransmitFile will not recycle the
- * accept socket (usually when the client disconnects early).
- * Get a new socket and try the call again.
+ /* Hack alert, we can get here because:
+ * 1) Occasionally, TransmitFile will not recycle the accept socket
+ * (usually when the client disconnects early).
+ * 2) There is VPN or Firewall software installed with buggy AcceptEx implementation
+ * 3) The webserver is using a dynamic address and it has changed
*/
+ Sleep(0);
+ if (++err_count > 1000) {
+ apr_int32_t disconnected;
+
+ /* abitrary socket call to test if the Listening socket is still valid */
+ apr_status_t listen_rv = apr_socket_opt_get(lr->sd, APR_SO_DISCONNECTED, &disconnected);
+
+ if (listen_rv == APR_SUCCESS) {
+ ap_log_error(APLOG_MARK,APLOG_ERR, listen_rv, ap_server_conf,
+ "AcceptEx error: If this occurs constantly and NO requests are being served "
+ "try using the WindowsSocketsWorkaround directive set to 'on'.");
+ err_count = 0;
+ }
+ else {
+ ap_log_error(APLOG_MARK,APLOG_ERR, listen_rv, ap_server_conf,
+ "The Listening socket is no longer valid. Dynamic address changed?");
+ break;
+ }
+ }
+
closesocket(context->accept_socket);
context->accept_socket = INVALID_SOCKET;
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf,
- "winnt_accept: AcceptEx failed due to early client "
- "disconnect. Reallocate the accept socket and try again.");
+ "winnt_accept: AcceptEx failed, either early client disconnect, "
+ "dynamic address renewal, or incompatible VPN or Firewall software.");
+
continue;
}
else if ((rv != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) &&
@@ -558,6 +581,7 @@ static void winnt_accept(void *lr_)
Sleep(100);
continue;
}
+ err_count = 0;
/* Wait for pending i/o.
* Wake up once per second to check for shutdown .
@@ -701,7 +725,7 @@ static void worker_main(long thread_num)
ap_update_child_status_from_indexes(0, thread_num, SERVER_READY, NULL);
/* Grab a connection off the network */
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
+ if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS || windows_sockets_workaround == 1) {
context = win9x_get_connection(context);
}
else {
@@ -769,7 +793,7 @@ static void cleanup_thread(HANDLE *handles, int *thread_cnt, int thread_to_clean
static void create_listener_thread()
{
int tid;
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
+ if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS || windows_sockets_workaround == 1) {
_beginthreadex(NULL, 0, (LPTHREAD_START_ROUTINE) win9x_accept,
NULL, 0, &tid);
} else {
@@ -840,7 +864,7 @@ void child_main(apr_pool_t *pconf)
* Create the worker thread dispatch IOCompletionPort
* on Windows NT/2000
*/
- if (osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) {
+ if (osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS && windows_sockets_workaround != 1) {
/* Create the worker thread dispatch IOCP */
ThreadDispatchIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
NULL,
@@ -1007,7 +1031,7 @@ void child_main(apr_pool_t *pconf)
}
/* Shutdown the worker threads */
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
+ if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS || windows_sockets_workaround == 1) {
for (i = 0; i < threads_created; i++) {
add_job(INVALID_SOCKET);
}
@@ -1065,7 +1089,7 @@ void child_main(apr_pool_t *pconf)
CloseHandle(allowed_globals.jobsemaphore);
apr_thread_mutex_destroy(allowed_globals.jobmutex);
- if (osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) {
+ if (osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS && windows_sockets_workaround != 1) {
apr_thread_mutex_destroy(qlock);
CloseHandle(qwait_event);
}
diff --git a/server/mpm/winnt/mpm_winnt.c b/server/mpm/winnt/mpm_winnt.c
index 0ce69fb663..f82c36dbb8 100644
--- a/server/mpm/winnt/mpm_winnt.c
+++ b/server/mpm/winnt/mpm_winnt.c
@@ -102,6 +102,7 @@ OSVERSIONINFO osver; /* VER_PLATFORM_WIN32_NT */
static DWORD parent_pid;
DWORD my_pid;
+int windows_sockets_workaround = 0;
int ap_threads_per_child = 0;
static int thread_limit = DEFAULT_THREAD_LIMIT;
static int first_thread_limit = 0;
@@ -217,6 +218,24 @@ static const char *set_thread_limit (cmd_parms *cmd, void *dummy, const char *ar
}
return NULL;
}
+static const char *set_sockets_workaround (cmd_parms *cmd, void *dummy, char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+
+ windows_sockets_workaround = 0;
+ if (!strcasecmp(arg, "on")) {
+ windows_sockets_workaround = 1;
+ }
+ else if (strcasecmp(arg, "off")) {
+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+ "WARNING: setting WindowsSocketsWorkaround to off");
+ }
+ return NULL;
+}
+
static const command_rec winnt_cmds[] = {
LISTEN_COMMANDS,
@@ -224,6 +243,9 @@ AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
"Number of threads each child creates" ),
AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
"Maximum worker threads in a server for this run of Apache"),
+AP_INIT_TAKE1("WindowsSocketsWorkaround", set_sockets_workaround, NULL, RSRC_CONF,
+ "Set \"on\" to work around buggy Winsock provider implementations of certain VPN or Firewall software"),
+
{ NULL }
};
diff --git a/server/mpm/winnt/mpm_winnt.h b/server/mpm/winnt/mpm_winnt.h
index 5046553dd9..79d72c8b01 100644
--- a/server/mpm/winnt/mpm_winnt.h
+++ b/server/mpm/winnt/mpm_winnt.h
@@ -101,6 +101,7 @@ void mpm_nt_eventlog_stderr_flush(void);
/* From winnt.c: */
+extern int windows_sockets_workaround;
extern OSVERSIONINFO osver;
extern void clean_child_exit(int);