mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 07:23:03 +01:00
Fixed bug CORE-3119 : 100% CPU USAGE with Unilimited Loop & Index corrupted
This commit is contained in:
parent
05bac17bc4
commit
b48821ac02
@ -125,7 +125,7 @@ const USHORT MAX_PTYPE = ptype_lazy_send;
|
||||
#include <process.h>
|
||||
#include <signal.h>
|
||||
#include "../utilities/install/install_nt.h"
|
||||
#define SOCLOSE closesocket
|
||||
|
||||
#define INET_RETRY_ERRNO WSAEINPROGRESS
|
||||
#define INET_ADDR_IN_USE WSAEADDRINUSE
|
||||
#define sleep(seconds) Sleep ((seconds) * 1000)
|
||||
@ -133,9 +133,6 @@ const int NOTASOCKET = WSAENOTSOCK;
|
||||
|
||||
#else // WIN_NT
|
||||
|
||||
#ifndef SOCLOSE
|
||||
#define SOCLOSE close
|
||||
#endif
|
||||
#ifndef INET_ADDR_IN_USE
|
||||
#define INET_ADDR_IN_USE EADDRINUSE
|
||||
#endif
|
||||
@ -146,9 +143,19 @@ const int NOTASOCKET = EBADF;
|
||||
|
||||
#endif // WIN_NT
|
||||
|
||||
#ifndef INVALID_SOCKET
|
||||
#define INVALID_SOCKET -1
|
||||
|
||||
static void SOCLOSE(SOCKET& socket)
|
||||
{
|
||||
if (socket != INVALID_SOCKET)
|
||||
{
|
||||
#ifdef WIN_NT
|
||||
closesocket(socket);
|
||||
#else
|
||||
close(socket);
|
||||
#endif
|
||||
socket = INVALID_SOCKET;
|
||||
}
|
||||
};
|
||||
|
||||
// Can't find were it's used.
|
||||
//#ifndef SIGURG
|
||||
@ -235,7 +242,7 @@ static bool accept_connection(rem_port*, const P_CNCT*);
|
||||
#ifdef HAVE_SETITIMER
|
||||
static void alarm_handler(int);
|
||||
#endif
|
||||
static rem_port* alloc_port(rem_port*);
|
||||
static rem_port* alloc_port(rem_port*, const USHORT = 0);
|
||||
static rem_port* aux_connect(rem_port*, PACKET*);
|
||||
static rem_port* aux_request(rem_port*, PACKET*);
|
||||
|
||||
@ -1142,7 +1149,7 @@ static bool accept_connection(rem_port* port, const P_CNCT* cnct)
|
||||
}
|
||||
|
||||
|
||||
static rem_port* alloc_port(rem_port* const parent)
|
||||
static rem_port* alloc_port(rem_port* const parent, const USHORT flags)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1217,6 +1224,7 @@ static rem_port* alloc_port(rem_port* const parent)
|
||||
port->port_request = aux_request;
|
||||
port->port_buff_size = (USHORT) INET_remote_buffer;
|
||||
port->port_async_receive = inet_async_receive;
|
||||
port->port_flags = flags;
|
||||
|
||||
xdrinet_create( &port->port_send, port,
|
||||
&port->port_buffer[INET_remote_buffer],
|
||||
@ -1254,15 +1262,15 @@ static rem_port* aux_connect(rem_port* port, PACKET* packet)
|
||||
|
||||
if (port->port_server_flags)
|
||||
{
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = port->port_connect_timeout;
|
||||
timeout.tv_usec = 0;
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = port->port_connect_timeout;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
fd_set slct_fdset;
|
||||
FD_ZERO(&slct_fdset);
|
||||
FD_SET(port->port_channel, &slct_fdset);
|
||||
fd_set slct_fdset;
|
||||
FD_ZERO(&slct_fdset);
|
||||
FD_SET(port->port_channel, &slct_fdset);
|
||||
|
||||
int inetErrNo = 0;
|
||||
int inetErrNo = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -1425,14 +1433,14 @@ static rem_port* aux_request( rem_port* port, PACKET* packet)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rem_port* const new_port = alloc_port(port->port_parent);
|
||||
rem_port* const new_port = alloc_port(port->port_parent, PORT_async);
|
||||
port->port_async = new_port;
|
||||
new_port->port_dummy_packet_interval = port->port_dummy_packet_interval;
|
||||
new_port->port_dummy_timeout = new_port->port_dummy_packet_interval;
|
||||
|
||||
new_port->port_server_flags = port->port_server_flags;
|
||||
new_port->port_channel = (int) n;
|
||||
new_port->port_flags = port->port_flags & PORT_no_oob;
|
||||
new_port->port_flags |= port->port_flags & PORT_no_oob;
|
||||
|
||||
P_RESP* response = &packet->p_resp;
|
||||
|
||||
@ -1530,11 +1538,7 @@ static void disconnect(rem_port* const port)
|
||||
(SCHAR*) &port->port_linger, sizeof(port->port_linger));
|
||||
}
|
||||
|
||||
#if defined WIN_NT
|
||||
if (port->port_handle && port->port_handle != INVALID_SOCKET)
|
||||
#else
|
||||
if (port->port_handle)
|
||||
#endif
|
||||
if (port->port_handle != INVALID_SOCKET)
|
||||
{
|
||||
shutdown(port->port_handle, 2);
|
||||
}
|
||||
@ -1553,9 +1557,8 @@ static void disconnect(rem_port* const port)
|
||||
|
||||
inet_ports->unRegisterPort(port);
|
||||
|
||||
if (port->port_handle) {
|
||||
SOCLOSE(port->port_handle);
|
||||
}
|
||||
SOCLOSE(port->port_handle);
|
||||
SOCLOSE(port->port_channel);
|
||||
|
||||
port->release();
|
||||
|
||||
@ -1592,17 +1595,10 @@ static void force_close(rem_port* port)
|
||||
|
||||
port->port_state = rem_port::BROKEN;
|
||||
|
||||
const SOCKET handle = port->port_handle;
|
||||
port->port_handle = 0;
|
||||
|
||||
#ifdef WIN_NT
|
||||
if (handle && handle != INVALID_SOCKET)
|
||||
#else
|
||||
if (handle)
|
||||
#endif
|
||||
if (port->port_handle != INVALID_SOCKET)
|
||||
{
|
||||
shutdown(handle, 2);
|
||||
SOCLOSE(handle);
|
||||
shutdown(port->port_handle, 2);
|
||||
SOCLOSE(port->port_handle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1970,9 +1966,9 @@ static bool select_multi(rem_port* main_port, UCHAR* buffer, SSHORT bufsize, SSH
|
||||
if (main_port->port_state != rem_port::BROKEN)
|
||||
{
|
||||
main_port->port_state = rem_port::BROKEN;
|
||||
const SOCKET s = main_port->port_handle;
|
||||
shutdown(s, 2);
|
||||
SOCLOSE(s);
|
||||
|
||||
shutdown(main_port->port_handle, 2);
|
||||
SOCLOSE(main_port->port_handle);
|
||||
}
|
||||
}
|
||||
else if (port = select_accept(main_port))
|
||||
@ -2082,8 +2078,12 @@ static void select_port(rem_port* main_port, slct_t* selct, RemPortPtr& port)
|
||||
#ifdef WIN_NT
|
||||
const int ok = FD_ISSET(n, &selct->slct_fdset);
|
||||
#else
|
||||
if (n < 0 || n >= FD_SETSIZE) {
|
||||
return;
|
||||
if (n < 0 || n >= FD_SETSIZE)
|
||||
{
|
||||
if (port->port_flags & PORT_disconnect)
|
||||
continue;
|
||||
else
|
||||
return;
|
||||
}
|
||||
const int ok = n < selct->slct_width && FD_ISSET(n, &selct->slct_fdset);
|
||||
#endif
|
||||
@ -2142,7 +2142,9 @@ static bool select_wait( rem_port* main_port, slct_t* selct)
|
||||
Firebird::MutexLockGuard guard(port_mutex);
|
||||
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 &&
|
||||
// don't wait on still listening (not connected) async port
|
||||
!(port->port_handle == INVALID_SOCKET && port->port_flags & PORT_async))
|
||||
{
|
||||
// Adjust down the port's keepalive timer.
|
||||
|
||||
|
@ -591,7 +591,6 @@ void rem_port::linkParent(rem_port* const parent)
|
||||
|
||||
this->port_parent = parent;
|
||||
this->port_next = parent->port_clients;
|
||||
this->port_handle = parent->port_handle;
|
||||
this->port_server = parent->port_server;
|
||||
this->port_server_flags = parent->port_server_flags;
|
||||
|
||||
|
@ -53,6 +53,10 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifndef INVALID_SOCKET
|
||||
#define INVALID_SOCKET -1
|
||||
#endif
|
||||
#endif // !WIN_NT
|
||||
|
||||
|
||||
@ -79,7 +83,6 @@ const int BLOB_LENGTH = 16384;
|
||||
#include "../remote/protocol.h"
|
||||
#include "fb_blk.h"
|
||||
|
||||
|
||||
// fwd. decl.
|
||||
struct rem_port;
|
||||
|
||||
@ -585,6 +588,7 @@ const USHORT PORT_partial_data = 0x0080; // Physical packet doesn't contain all
|
||||
const USHORT PORT_lazy = 0x0100; // Deferred operations are allowed
|
||||
const USHORT PORT_server = 0x0200; // Server (not client) port
|
||||
const USHORT PORT_detached = 0x0400; // op_detach, op_drop_database or op_service_detach was processed
|
||||
const USHORT PORT_rdb_shutdown = 0x0800; // Database is shutted down
|
||||
|
||||
// Port itself
|
||||
|
||||
@ -643,7 +647,7 @@ struct rem_port : public Firebird::GlobalStorage, public Firebird::RefCounted
|
||||
SLONG port_dummy_timeout; // time remaining until keepalive packet
|
||||
ISC_STATUS* port_status_vector;
|
||||
SOCKET port_handle; // handle for INET socket
|
||||
int port_channel; // handle for connection (from by OS)
|
||||
SOCKET port_channel; // handle for connection (from by OS)
|
||||
struct linger port_linger; // linger value as defined by SO_LINGER
|
||||
Rdb* port_context;
|
||||
ThreadHandle port_events_thread; // handle of thread, handling incoming events
|
||||
@ -694,7 +698,7 @@ public:
|
||||
port_clients(0), port_next(0), port_parent(0), port_async(0), port_async_receive(0),
|
||||
port_server(0), port_server_flags(0), port_protocol(0), port_buff_size(0),
|
||||
port_flags(0), port_connect_timeout(0), port_dummy_packet_interval(0),
|
||||
port_dummy_timeout(0), port_status_vector(0), port_handle(0), port_channel(0),
|
||||
port_dummy_timeout(0), port_status_vector(0), port_handle(INVALID_SOCKET), port_channel(INVALID_SOCKET),
|
||||
port_context(0), port_events_thread(0), port_events_shutdown(0),
|
||||
#ifdef WIN_NT
|
||||
port_pipe(INVALID_HANDLE_VALUE), port_event(INVALID_HANDLE_VALUE),
|
||||
|
@ -1308,8 +1308,21 @@ static void aux_request( rem_port* port, /*P_REQ* request,*/ PACKET* send)
|
||||
|
||||
if (aux_port)
|
||||
{
|
||||
aux_port->connect(send);
|
||||
aux_port->port_context = rdb;
|
||||
ISC_STATUS* const save_status = aux_port->port_status_vector;
|
||||
aux_port->port_status_vector = status_vector;
|
||||
|
||||
if (aux_port->connect(send))
|
||||
{
|
||||
aux_port->port_context = rdb;
|
||||
aux_port->port_status_vector = save_status;
|
||||
}
|
||||
else
|
||||
{
|
||||
iscLogStatus(NULL, aux_port->port_status_vector);
|
||||
fb_assert(port->port_async == aux_port);
|
||||
port->port_async = NULL;
|
||||
aux_port->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
// restore the port status vector
|
||||
@ -3514,7 +3527,7 @@ static bool process_packet(rem_port* port, PACKET* sendL, PACKET* receive, rem_p
|
||||
{
|
||||
if (!port->port_parent)
|
||||
{
|
||||
if (!Worker::isShuttingDown())
|
||||
if (!Worker::isShuttingDown() && !(port->port_flags & PORT_rdb_shutdown))
|
||||
gds__log("SERVER/process_packet: broken port, server exiting");
|
||||
port->disconnect(sendL, receive);
|
||||
return false;
|
||||
@ -4600,6 +4613,7 @@ ISC_STATUS rem_port::send_response( PACKET* sendL,
|
||||
if (exit_code == isc_shutdown || exit_code == isc_att_shutdown)
|
||||
{
|
||||
this->port_state = rem_port::BROKEN;
|
||||
this->port_flags |= PORT_rdb_shutdown;
|
||||
}
|
||||
|
||||
return exit_code;
|
||||
|
Loading…
Reference in New Issue
Block a user