From: <hv...@us...> - 2010-12-12 20:19:53
|
Revision: 52038 http://firebird.svn.sourceforge.net/firebird/?rev=52038&view=rev Author: hvlad Date: 2010-12-12 20:19:47 +0000 (Sun, 12 Dec 2010) Log Message: ----------- Port forward fix for bug CORE-3119 : 100% CPU USAGE with Unilimited Loop & Index corrupted Modified Paths: -------------- firebird/trunk/src/remote/inet.cpp firebird/trunk/src/remote/remote.cpp firebird/trunk/src/remote/remote.h firebird/trunk/src/remote/server/server.cpp Modified: firebird/trunk/src/remote/inet.cpp =================================================================== --- firebird/trunk/src/remote/inet.cpp 2010-12-12 19:53:27 UTC (rev 52037) +++ firebird/trunk/src/remote/inet.cpp 2010-12-12 20:19:47 UTC (rev 52038) @@ -125,7 +125,7 @@ #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 @@ #else // WIN_NT -#ifndef SOCLOSE -#define SOCLOSE close -#endif #ifndef INET_ADDR_IN_USE #define INET_ADDR_IN_USE EADDRINUSE #endif @@ -146,9 +143,18 @@ #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 +241,7 @@ #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*); @@ -1050,7 +1056,7 @@ } -static rem_port* alloc_port(rem_port* const parent) +static rem_port* alloc_port(rem_port* const parent, const USHORT flags) { /************************************** * @@ -1120,6 +1126,7 @@ 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], @@ -1323,14 +1330,14 @@ inet_error(false, port, "listen", isc_net_event_listen_err, INET_ERRNO); } - 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; @@ -1427,11 +1434,7 @@ (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); } @@ -1450,9 +1453,8 @@ inet_ports->unRegisterPort(port); - if (port->port_handle) { - SOCLOSE(port->port_handle); - } + SOCLOSE(port->port_handle); + SOCLOSE(port->port_channel); port->release(); @@ -1489,17 +1491,10 @@ 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); } } @@ -1870,9 +1865,9 @@ 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)) @@ -1980,8 +1975,12 @@ #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 @@ -2040,8 +2039,10 @@ 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. if (port->port_dummy_packet_interval) Modified: firebird/trunk/src/remote/remote.cpp =================================================================== --- firebird/trunk/src/remote/remote.cpp 2010-12-12 19:53:27 UTC (rev 52037) +++ firebird/trunk/src/remote/remote.cpp 2010-12-12 20:19:47 UTC (rev 52038) @@ -590,7 +590,6 @@ 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; Modified: firebird/trunk/src/remote/remote.h =================================================================== --- firebird/trunk/src/remote/remote.h 2010-12-12 19:53:27 UTC (rev 52037) +++ firebird/trunk/src/remote/remote.h 2010-12-12 20:19:47 UTC (rev 52038) @@ -46,6 +46,10 @@ #include <fcntl.h> #include <sys/socket.h> #include <sys/ioctl.h> + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET -1 +#endif #endif // !WIN_NT @@ -566,6 +570,7 @@ 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 @@ -622,7 +627,7 @@ 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; Thread::Handle port_events_thread; // handle of thread, handling incoming events @@ -667,7 +672,7 @@ 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), Modified: firebird/trunk/src/remote/server/server.cpp =================================================================== --- firebird/trunk/src/remote/server/server.cpp 2010-12-12 19:53:27 UTC (rev 52037) +++ firebird/trunk/src/remote/server/server.cpp 2010-12-12 20:19:47 UTC (rev 52038) @@ -1541,15 +1541,23 @@ } if (aux_port) + try + { + if (aux_port->connect(send)) + aux_port->port_context = rdb; + } + catch (const Exception& ex) + { + iscLogException("", ex); + fb_assert(port->port_async == aux_port); + port->port_async = NULL; + aux_port->disconnect(); + } + } + catch (const Exception& ex) { - aux_port->connect(send); - aux_port->port_context = rdb; + iscLogException("Unhandled exception in server's aux_request():", ex); } - } - catch (const Exception& ex) - { - iscLogException("Unhandled exception in server's aux_request():", ex); - } } @@ -3744,7 +3752,7 @@ { 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; @@ -4569,6 +4577,7 @@ 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; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |