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

Fixed bug CORE-3119 : 100% CPU USAGE with Unilimited Loop & Index corrupted

This commit is contained in:
hvlad 2010-12-12 19:17:37 +00:00
parent 05bac17bc4
commit b48821ac02
4 changed files with 67 additions and 48 deletions

View File

@ -125,7 +125,7 @@ const USHORT MAX_PTYPE = ptype_lazy_send;
#include <process.h> #include <process.h>
#include <signal.h> #include <signal.h>
#include "../utilities/install/install_nt.h" #include "../utilities/install/install_nt.h"
#define SOCLOSE closesocket
#define INET_RETRY_ERRNO WSAEINPROGRESS #define INET_RETRY_ERRNO WSAEINPROGRESS
#define INET_ADDR_IN_USE WSAEADDRINUSE #define INET_ADDR_IN_USE WSAEADDRINUSE
#define sleep(seconds) Sleep ((seconds) * 1000) #define sleep(seconds) Sleep ((seconds) * 1000)
@ -133,9 +133,6 @@ const int NOTASOCKET = WSAENOTSOCK;
#else // WIN_NT #else // WIN_NT
#ifndef SOCLOSE
#define SOCLOSE close
#endif
#ifndef INET_ADDR_IN_USE #ifndef INET_ADDR_IN_USE
#define INET_ADDR_IN_USE EADDRINUSE #define INET_ADDR_IN_USE EADDRINUSE
#endif #endif
@ -146,9 +143,19 @@ const int NOTASOCKET = EBADF;
#endif // WIN_NT #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 #endif
socket = INVALID_SOCKET;
}
};
// Can't find were it's used. // Can't find were it's used.
//#ifndef SIGURG //#ifndef SIGURG
@ -235,7 +242,7 @@ static bool accept_connection(rem_port*, const P_CNCT*);
#ifdef HAVE_SETITIMER #ifdef HAVE_SETITIMER
static void alarm_handler(int); static void alarm_handler(int);
#endif #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_connect(rem_port*, PACKET*);
static rem_port* aux_request(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_request = aux_request;
port->port_buff_size = (USHORT) INET_remote_buffer; port->port_buff_size = (USHORT) INET_remote_buffer;
port->port_async_receive = inet_async_receive; port->port_async_receive = inet_async_receive;
port->port_flags = flags;
xdrinet_create( &port->port_send, port, xdrinet_create( &port->port_send, port,
&port->port_buffer[INET_remote_buffer], &port->port_buffer[INET_remote_buffer],
@ -1425,14 +1433,14 @@ static rem_port* aux_request( rem_port* port, PACKET* packet)
return NULL; 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; port->port_async = new_port;
new_port->port_dummy_packet_interval = port->port_dummy_packet_interval; 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_dummy_timeout = new_port->port_dummy_packet_interval;
new_port->port_server_flags = port->port_server_flags; new_port->port_server_flags = port->port_server_flags;
new_port->port_channel = (int) n; 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; 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)); (SCHAR*) &port->port_linger, sizeof(port->port_linger));
} }
#if defined WIN_NT if (port->port_handle != INVALID_SOCKET)
if (port->port_handle && port->port_handle != INVALID_SOCKET)
#else
if (port->port_handle)
#endif
{ {
shutdown(port->port_handle, 2); shutdown(port->port_handle, 2);
} }
@ -1553,9 +1557,8 @@ static void disconnect(rem_port* const port)
inet_ports->unRegisterPort(port); inet_ports->unRegisterPort(port);
if (port->port_handle) {
SOCLOSE(port->port_handle); SOCLOSE(port->port_handle);
} SOCLOSE(port->port_channel);
port->release(); port->release();
@ -1592,17 +1595,10 @@ static void force_close(rem_port* port)
port->port_state = rem_port::BROKEN; port->port_state = rem_port::BROKEN;
const SOCKET handle = port->port_handle; if (port->port_handle != INVALID_SOCKET)
port->port_handle = 0;
#ifdef WIN_NT
if (handle && handle != INVALID_SOCKET)
#else
if (handle)
#endif
{ {
shutdown(handle, 2); shutdown(port->port_handle, 2);
SOCLOSE(handle); 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) if (main_port->port_state != rem_port::BROKEN)
{ {
main_port->port_state = rem_port::BROKEN; main_port->port_state = rem_port::BROKEN;
const SOCKET s = main_port->port_handle;
shutdown(s, 2); shutdown(main_port->port_handle, 2);
SOCLOSE(s); SOCLOSE(main_port->port_handle);
} }
} }
else if (port = select_accept(main_port)) else if (port = select_accept(main_port))
@ -2082,7 +2078,11 @@ static void select_port(rem_port* main_port, slct_t* selct, RemPortPtr& port)
#ifdef WIN_NT #ifdef WIN_NT
const int ok = FD_ISSET(n, &selct->slct_fdset); const int ok = FD_ISSET(n, &selct->slct_fdset);
#else #else
if (n < 0 || n >= FD_SETSIZE) { if (n < 0 || n >= FD_SETSIZE)
{
if (port->port_flags & PORT_disconnect)
continue;
else
return; return;
} }
const int ok = n < selct->slct_width && FD_ISSET(n, &selct->slct_fdset); const int ok = n < selct->slct_width && FD_ISSET(n, &selct->slct_fdset);
@ -2142,7 +2142,9 @@ static bool select_wait( rem_port* main_port, slct_t* selct)
Firebird::MutexLockGuard guard(port_mutex); Firebird::MutexLockGuard guard(port_mutex);
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 &&
// 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. // Adjust down the port's keepalive timer.

View File

@ -591,7 +591,6 @@ void rem_port::linkParent(rem_port* const parent)
this->port_parent = parent; this->port_parent = parent;
this->port_next = parent->port_clients; this->port_next = parent->port_clients;
this->port_handle = parent->port_handle;
this->port_server = parent->port_server; this->port_server = parent->port_server;
this->port_server_flags = parent->port_server_flags; this->port_server_flags = parent->port_server_flags;

View File

@ -53,6 +53,10 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#ifndef INVALID_SOCKET
#define INVALID_SOCKET -1
#endif
#endif // !WIN_NT #endif // !WIN_NT
@ -79,7 +83,6 @@ const int BLOB_LENGTH = 16384;
#include "../remote/protocol.h" #include "../remote/protocol.h"
#include "fb_blk.h" #include "fb_blk.h"
// fwd. decl. // fwd. decl.
struct rem_port; 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_lazy = 0x0100; // Deferred operations are allowed
const USHORT PORT_server = 0x0200; // Server (not client) port 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_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 // Port itself
@ -643,7 +647,7 @@ struct rem_port : public Firebird::GlobalStorage, public Firebird::RefCounted
SLONG port_dummy_timeout; // time remaining until keepalive packet SLONG port_dummy_timeout; // time remaining until keepalive packet
ISC_STATUS* port_status_vector; ISC_STATUS* port_status_vector;
SOCKET port_handle; // handle for INET socket 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 struct linger port_linger; // linger value as defined by SO_LINGER
Rdb* port_context; Rdb* port_context;
ThreadHandle port_events_thread; // handle of thread, handling incoming events 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_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_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_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), port_context(0), port_events_thread(0), port_events_shutdown(0),
#ifdef WIN_NT #ifdef WIN_NT
port_pipe(INVALID_HANDLE_VALUE), port_event(INVALID_HANDLE_VALUE), port_pipe(INVALID_HANDLE_VALUE), port_event(INVALID_HANDLE_VALUE),

View File

@ -1308,8 +1308,21 @@ static void aux_request( rem_port* port, /*P_REQ* request,*/ PACKET* send)
if (aux_port) if (aux_port)
{ {
aux_port->connect(send); 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_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 // 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 (!port->port_parent)
{ {
if (!Worker::isShuttingDown()) if (!Worker::isShuttingDown() && !(port->port_flags & PORT_rdb_shutdown))
gds__log("SERVER/process_packet: broken port, server exiting"); gds__log("SERVER/process_packet: broken port, server exiting");
port->disconnect(sendL, receive); port->disconnect(sendL, receive);
return false; return false;
@ -4600,6 +4613,7 @@ ISC_STATUS rem_port::send_response( PACKET* sendL,
if (exit_code == isc_shutdown || exit_code == isc_att_shutdown) if (exit_code == isc_shutdown || exit_code == isc_att_shutdown)
{ {
this->port_state = rem_port::BROKEN; this->port_state = rem_port::BROKEN;
this->port_flags |= PORT_rdb_shutdown;
} }
return exit_code; return exit_code;