|
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.
|