8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 01:23:03 +01:00

Fixed bug CORE-2107 : Failed to establish TCP\IP connection with Windows Classic Server under high load

This commit is contained in:
hvlad 2008-10-04 17:14:51 +00:00
parent 774635c3a9
commit c56ebce7bc

View File

@ -54,10 +54,7 @@
#include "../common/classes/timestamp.h"
#include "../common/classes/init.h"
#if !defined(WIN_NT)
#include "../jrd/ThreadStart.h"
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
@ -265,6 +262,15 @@ static int fork(void);
#ifdef WIN_NT
static void wsaExitHandler(void*);
static int fork(SOCKET, USHORT);
static THREAD_ENTRY_DECLARE forkThread(THREAD_ENTRY_PARAM);
static Firebird::GlobalPtr<Firebird::Mutex> forkMutex;
static HANDLE forkEvent = INVALID_HANDLE_VALUE;
static bool forkThreadStarted = false;
typedef Firebird::Array<SOCKET> SocketsArray;
static SocketsArray *forkSockets;
#endif
static in_addr get_bind_address();
@ -366,6 +372,7 @@ static XDR::xdr_ops inet_ops =
SLONG INET_remote_buffer;
static Firebird::GlobalPtr<Firebird::Mutex> init_mutex;
static bool INET_initialized = false;
static bool INET_shutting_down = false;
static SLCT INET_select = { 0, 0, 0 };
@ -886,7 +893,7 @@ rem_port* INET_connect(const TEXT* name,
return NULL;
}
#ifdef WIN_NT
if ((flag & SRVR_debug) || !fork(s, flag))
if (flag & SRVR_debug)
#else
if ((flag & SRVR_debug) || !fork())
#endif
@ -903,9 +910,37 @@ rem_port* INET_connect(const TEXT* name,
gds__thread_start(waitThread, 0, THREAD_medium, 0, 0);
}
#endif
#ifdef WIN_NT
Firebird::MutexLockGuard forkGuard(forkMutex);
if (!forkThreadStarted)
{
forkThreadStarted = true;
forkEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
forkSockets = new SocketsArray(*getDefaultMemoryPool());
gds__thread_start(forkThread, (void*) flag, THREAD_medium, 0, 0);
}
forkSockets->add(s);
SetEvent(forkEvent);
#else
SOCLOSE(s);
#endif
}
#ifdef WIN_NT
Firebird::MutexLockGuard forkGuard(forkMutex);
if (forkThreadStarted)
{
SetEvent(forkEvent);
CloseHandle(forkEvent);
delete forkSockets;
forkSockets = NULL;
}
#endif
}
rem_port* INET_reconnect(HANDLE handle, ISC_STATUS* status_vector)
{
@ -1193,6 +1228,9 @@ static rem_port* alloc_port( rem_port* parent)
if (!INET_initialized)
{
Firebird::MutexLockGuard guard(init_mutex);
if (!INET_initialized)
{
#ifdef WIN_NT
static WSADATA wsadata;
const WORD version = MAKEWORD(2, 0);
@ -1225,6 +1263,7 @@ static rem_port* alloc_port( rem_port* parent)
inet_async_receive = alloc_port(0);
inet_async_receive->port_flags |= PORT_server;
}
}
rem_port* port = new rem_port(rem_port::INET, INET_remote_buffer * 2);
REMOTE_get_timeout_params(port, 0);
@ -1782,9 +1821,12 @@ static int fork( SOCKET old_handle, USHORT flag)
GetModuleFileName(NULL, name, sizeof(name));
HANDLE new_handle;
DuplicateHandle(GetCurrentProcess(), (HANDLE) old_handle,
GetCurrentProcess(), &new_handle, 0, TRUE,
DUPLICATE_SAME_ACCESS);
if (!DuplicateHandle(GetCurrentProcess(), (HANDLE) old_handle,
GetCurrentProcess(), &new_handle, 0, TRUE, DUPLICATE_SAME_ACCESS))
{
gds__log("INET/inet_error: fork/DuplicateHandle errno = %d", GetLastError());
return 0;
}
Firebird::string cmdLine;
cmdLine.printf("%s -i -h %"SLONGFORMAT, name, (SLONG) new_handle);
@ -1807,11 +1849,43 @@ static int fork( SOCKET old_handle, USHORT flag)
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
CloseHandle(new_handle);
return 1;
}
gds__log("INET/inet_error: fork/CreateProcess errno = %d", GetLastError());
CloseHandle(new_handle);
return 0;
}
THREAD_ENTRY_DECLARE forkThread(THREAD_ENTRY_PARAM arg)
{
const USHORT flag = (USHORT) arg;
while (!INET_shutting_down)
{
if (WaitForSingleObject(forkEvent, INFINITE) != WAIT_OBJECT_0)
break;
while (!INET_shutting_down)
{
SOCKET s = 0;
{
Firebird::MutexLockGuard forkGuard(forkMutex);
if (!forkSockets || forkSockets->getCount() == 0)
break;
s = (*forkSockets)[0];
forkSockets->remove((size_t)0);
}
fork(s, flag);
SOCLOSE(s);
}
}
return 0;
}
#endif
namespace