mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 18:03:04 +01:00
Implemented delayed closing of server sockets - it should fix server hang up (see CORE-4680).
Fixed socket disconnect handling to allow graceful shutdown of network connection and avoid a lot of network errors in firebird.log (mostly 10053\10054). Misc changes.
This commit is contained in:
parent
5ab91b67dd
commit
4068a225b4
@ -425,8 +425,10 @@ static int cleanup_ports(const int, const int, void*);
|
|||||||
static int fork();
|
static int fork();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef Array<SOCKET> SocketsArray;
|
||||||
|
|
||||||
#ifdef WIN_NT
|
#ifdef WIN_NT
|
||||||
static void wsaExitHandler(void*);
|
static int wsaExitHandler(const int, const int, void*);
|
||||||
static int fork(SOCKET, USHORT);
|
static int fork(SOCKET, USHORT);
|
||||||
static THREAD_ENTRY_DECLARE forkThread(THREAD_ENTRY_PARAM);
|
static THREAD_ENTRY_DECLARE forkThread(THREAD_ENTRY_PARAM);
|
||||||
|
|
||||||
@ -434,9 +436,7 @@ static GlobalPtr<Mutex> forkMutex;
|
|||||||
static HANDLE forkEvent = INVALID_HANDLE_VALUE;
|
static HANDLE forkEvent = INVALID_HANDLE_VALUE;
|
||||||
static bool forkThreadStarted = false;
|
static bool forkThreadStarted = false;
|
||||||
|
|
||||||
typedef Array<SOCKET> SocketsArray;
|
|
||||||
static SocketsArray* forkSockets;
|
static SocketsArray* forkSockets;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void inet_gen_error(bool, rem_port*, const Arg::StatusVector& v);
|
static void inet_gen_error(bool, rem_port*, const Arg::StatusVector& v);
|
||||||
@ -520,6 +520,7 @@ static rem_port* inet_async_receive = NULL;
|
|||||||
|
|
||||||
static GlobalPtr<Mutex> port_mutex;
|
static GlobalPtr<Mutex> port_mutex;
|
||||||
static GlobalPtr<PortsCleanup> inet_ports;
|
static GlobalPtr<PortsCleanup> inet_ports;
|
||||||
|
static GlobalPtr<SocketsArray> ports_to_close;
|
||||||
|
|
||||||
|
|
||||||
rem_port* INET_analyze(ClntAuthBlock* cBlock,
|
rem_port* INET_analyze(ClntAuthBlock* cBlock,
|
||||||
@ -1237,7 +1238,7 @@ static rem_port* alloc_port(rem_port* const parent, const USHORT flags)
|
|||||||
{
|
{
|
||||||
inet_error(false, parent, "WSAStartup", isc_net_init_error, wsaError);
|
inet_error(false, parent, "WSAStartup", isc_net_init_error, wsaError);
|
||||||
}
|
}
|
||||||
gds__register_cleanup(wsaExitHandler, 0);
|
fb_shutdown_callback(0, wsaExitHandler, fb_shut_finish, 0);
|
||||||
#endif
|
#endif
|
||||||
INET_remote_buffer = Config::getTcpRemoteBufferSize();
|
INET_remote_buffer = Config::getTcpRemoteBufferSize();
|
||||||
if (INET_remote_buffer < MAX_DATA_LW || INET_remote_buffer > MAX_DATA_HW)
|
if (INET_remote_buffer < MAX_DATA_LW || INET_remote_buffer > MAX_DATA_HW)
|
||||||
@ -1565,15 +1566,31 @@ static void disconnect(rem_port* const port)
|
|||||||
// is an attempt to return the socket to a state where a graceful shutdown can
|
// is an attempt to return the socket to a state where a graceful shutdown can
|
||||||
// occur.
|
// occur.
|
||||||
|
|
||||||
|
// hvlad: for graceful shutdown linger should be turned on (despite of default
|
||||||
|
// setting by OS)
|
||||||
|
{ // scope
|
||||||
|
struct linger lngr = {1, 10};
|
||||||
|
socklen_t optlen = sizeof(lngr);
|
||||||
|
|
||||||
if (port->port_linger.l_onoff)
|
if (port->port_linger.l_onoff)
|
||||||
{
|
lngr = port->port_linger;
|
||||||
setsockopt(port->port_handle, SOL_SOCKET, SO_LINGER,
|
|
||||||
(SCHAR*) &port->port_linger, sizeof(port->port_linger));
|
setsockopt(port->port_handle, SOL_SOCKET, SO_LINGER, (SCHAR*)&lngr, sizeof(lngr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port->port_handle != INVALID_SOCKET)
|
if (port->port_handle != INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
shutdown(port->port_handle, 2);
|
shutdown(port->port_handle, 1);
|
||||||
|
|
||||||
|
fd_set fd = {0};
|
||||||
|
FD_SET(port->port_handle, &fd);
|
||||||
|
timeval tm = {10, 0};
|
||||||
|
int n = select(1, &fd, NULL, NULL, &tm);
|
||||||
|
while (n > 0)
|
||||||
|
{
|
||||||
|
char buff[256];
|
||||||
|
n = recv(port->port_handle, buff, sizeof(buff), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MutexLockGuard guard(port_mutex, FB_FUNCTION);
|
MutexLockGuard guard(port_mutex, FB_FUNCTION);
|
||||||
@ -1586,13 +1603,29 @@ static void disconnect(rem_port* const port)
|
|||||||
}
|
}
|
||||||
port->port_context = NULL;
|
port->port_context = NULL;
|
||||||
|
|
||||||
|
// hvlad: delay closing of the server sockets to prevent its reuse
|
||||||
|
// by another (newly accepted) port until next select() call. See
|
||||||
|
// also select_wait() function.
|
||||||
|
const bool delayClose = (port->port_server_flags && port->port_parent);
|
||||||
|
|
||||||
// If this is a sub-port, unlink it from its parent
|
// If this is a sub-port, unlink it from its parent
|
||||||
port->unlinkParent();
|
port->unlinkParent();
|
||||||
|
|
||||||
inet_ports->unRegisterPort(port);
|
inet_ports->unRegisterPort(port);
|
||||||
|
|
||||||
|
if (delayClose)
|
||||||
|
{
|
||||||
|
if (port->port_handle != INVALID_SOCKET)
|
||||||
|
ports_to_close->push(port->port_handle);
|
||||||
|
|
||||||
|
if (port->port_channel != INVALID_SOCKET)
|
||||||
|
ports_to_close->push(port->port_channel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SOCLOSE(port->port_handle);
|
SOCLOSE(port->port_handle);
|
||||||
SOCLOSE(port->port_channel);
|
SOCLOSE(port->port_channel);
|
||||||
|
}
|
||||||
|
|
||||||
port->release();
|
port->release();
|
||||||
|
|
||||||
@ -1656,6 +1689,13 @@ static int cleanup_ports(const int, const int, void* /*arg*/)
|
|||||||
INET_shutting_down = true;
|
INET_shutting_down = true;
|
||||||
|
|
||||||
inet_ports->closePorts();
|
inet_ports->closePorts();
|
||||||
|
|
||||||
|
while (ports_to_close->hasData())
|
||||||
|
{
|
||||||
|
SOCKET s = ports_to_close->pop();
|
||||||
|
SOCLOSE(s);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1679,7 +1719,7 @@ static int fork()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WIN_NT
|
#ifdef WIN_NT
|
||||||
static void wsaExitHandler(void*)
|
static int wsaExitHandler(const int, const int, void*)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -1693,6 +1733,7 @@ static void wsaExitHandler(void*)
|
|||||||
**************************************/
|
**************************************/
|
||||||
SleepEx(0, FALSE); // let select in other thread(s) shutdown gracefully
|
SleepEx(0, FALSE); // let select in other thread(s) shutdown gracefully
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2037,6 +2078,13 @@ static bool select_wait( rem_port* main_port, Select* selct)
|
|||||||
|
|
||||||
{ // port_mutex scope
|
{ // port_mutex scope
|
||||||
MutexLockGuard guard(port_mutex, FB_FUNCTION);
|
MutexLockGuard guard(port_mutex, FB_FUNCTION);
|
||||||
|
|
||||||
|
while (ports_to_close->hasData())
|
||||||
|
{
|
||||||
|
SOCKET s = ports_to_close->pop();
|
||||||
|
SOCLOSE(s);
|
||||||
|
}
|
||||||
|
|
||||||
for (rem_port* port = main_port; port; port = port->port_next)
|
for (rem_port* port = main_port; port; port = port->port_next)
|
||||||
{
|
{
|
||||||
if (port->port_state == rem_port::PENDING &&
|
if (port->port_state == rem_port::PENDING &&
|
||||||
|
Loading…
Reference in New Issue
Block a user