From: <ale...@us...> - 2012-01-16 15:01:28
|
Revision: 53864 http://firebird.svn.sourceforge.net/firebird/?rev=53864&view=rev Author: alexpeshkoff Date: 2012-01-16 15:01:17 +0000 (Mon, 16 Jan 2012) Log Message: ----------- Fixed CORE-3718: Client Library Hangs after unsuccessful connection to remote auxiliary (events) port Modified Paths: -------------- firebird/trunk/src/remote/inet.cpp firebird/trunk/src/remote/protocol.cpp firebird/trunk/src/remote/protocol.h 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 2012-01-16 14:30:47 UTC (rev 53863) +++ firebird/trunk/src/remote/inet.cpp 2012-01-16 15:01:17 UTC (rev 53864) @@ -399,6 +399,7 @@ #endif static rem_port* alloc_port(rem_port*, const USHORT = 0); static rem_port* aux_connect(rem_port*, PACKET*); +static void abort_aux_connection(rem_port*); static rem_port* aux_request(rem_port*, PACKET*); #if !defined(WIN_NT) @@ -1296,6 +1297,7 @@ port->port_send_packet = send_full; port->port_send_partial = send_partial; port->port_connect = aux_connect; + port->port_abort_aux_connection = abort_aux_connection; port->port_request = aux_request; port->port_buff_size = (USHORT) INET_remote_buffer; port->port_async_receive = inet_async_receive; @@ -1317,6 +1319,15 @@ return port; } +static void abort_aux_connection(rem_port* port) +{ + if (port->port_flags & PORT_connecting) + { + shutdown(port->port_channel, 2); + SOCLOSE(port->port_channel); + } +} + static rem_port* aux_connect(rem_port* port, PACKET* packet) { /************************************** @@ -1396,8 +1407,9 @@ SOCKET n = socket(AF_INET, SOCK_STREAM, 0); if (n == INVALID_SOCKET) { - inet_error(false, port, "socket", isc_net_event_connect_err, INET_ERRNO); - return NULL; + int savedError = INET_ERRNO; + port->auxAcceptError(packet); + inet_error(false, port, "socket", isc_net_event_connect_err, savedError); } // NJK - Determine address and port to use. @@ -1414,6 +1426,7 @@ if (status != 0) { int savedError = INET_ERRNO; + port->auxAcceptError(packet); SOCLOSE(n); inet_error(false, port, "socket", isc_net_event_connect_err, savedError); } @@ -1430,6 +1443,7 @@ { int savedError = INET_ERRNO; SOCLOSE(n); + port->auxAcceptError(packet); inet_error(false, port, "connect", isc_net_event_connect_err, savedError); } @@ -1651,6 +1665,9 @@ * **************************************/ + if (port->port_async) + abort_aux_connection(port->port_async); + if (port->port_state != rem_port::PENDING) return; @@ -2127,7 +2144,7 @@ switch (result) { case Select::SEL_BAD: - if (port->port_state == rem_port::BROKEN) + if (port->port_state == rem_port::BROKEN || port->port_flags & PORT_connecting) continue; return; Modified: firebird/trunk/src/remote/protocol.cpp =================================================================== --- firebird/trunk/src/remote/protocol.cpp 2012-01-16 14:30:47 UTC (rev 53863) +++ firebird/trunk/src/remote/protocol.cpp 2012-01-16 15:01:17 UTC (rev 53864) @@ -280,6 +280,7 @@ case op_disconnect: case op_dummy: case op_ping: + case op_abort_aux_connection: return P_TRUE(xdrs, p); case op_connect: Modified: firebird/trunk/src/remote/protocol.h =================================================================== --- firebird/trunk/src/remote/protocol.h 2012-01-16 14:30:47 UTC (rev 53863) +++ firebird/trunk/src/remote/protocol.h 2012-01-16 15:01:17 UTC (rev 53864) @@ -275,6 +275,8 @@ op_accept_data = 94, // Server accepts connection and returns some data to client + op_abort_aux_connection = 95, // Async operation - stop waiting for async connection to arrive + op_max }; Modified: firebird/trunk/src/remote/remote.cpp =================================================================== --- firebird/trunk/src/remote/remote.cpp 2012-01-16 14:30:47 UTC (rev 53863) +++ firebird/trunk/src/remote/remote.cpp 2012-01-16 15:01:17 UTC (rev 53864) @@ -656,6 +656,14 @@ return (*this->port_select_multi)(this, buffer, bufsize, length, port); } +void rem_port::abort_aux_connection() +{ + if (this->port_abort_aux_connection) + { + (*this->port_abort_aux_connection)(this); + } +} + XDR_INT rem_port::send(PACKET* pckt) { return (*this->port_send_packet)(this, pckt); @@ -676,6 +684,16 @@ return (*this->port_request)(this, pckt); } +void rem_port::auxAcceptError(PACKET* packet) +{ + if (port_protocol >= PROTOCOL_VERSION13) + { + packet->p_operation = op_abort_aux_connection; + // Ignore error return - we are already processing auxiliary connection error from the wire + send(packet); + } +} + bool_t REMOTE_getbytes (XDR* xdrs, SCHAR* buff, u_int count) { /************************************** Modified: firebird/trunk/src/remote/remote.h =================================================================== --- firebird/trunk/src/remote/remote.h 2012-01-16 14:30:47 UTC (rev 53863) +++ firebird/trunk/src/remote/remote.h 2012-01-16 15:01:17 UTC (rev 53864) @@ -709,6 +709,7 @@ const USHORT PORT_server = 0x0080; // Server (not client) port const USHORT PORT_detached = 0x0100; // op_detach, op_drop_database or op_service_detach was processed const USHORT PORT_rdb_shutdown = 0x0200; // Database is shut down +const USHORT PORT_connecting = 0x0400; // Aux connection waits for a channel to be activated by client // Port itself @@ -737,6 +738,7 @@ t_port_connect port_connect; // Establish secondary connection rem_port* (*port_request)(rem_port*, PACKET*); // Request to establish secondary connection bool (*port_select_multi)(rem_port*, UCHAR*, SSHORT, SSHORT*, RemPortPtr&); // get packet from active port + void (*port_abort_aux_connection)(rem_port*); // stop waiting for secondary connection enum rem_port_t { INET, // Internet (TCP/IP) @@ -927,6 +929,7 @@ rem_port* connect(PACKET* pckt); rem_port* request(PACKET* pckt); bool select_multi(UCHAR* buffer, SSHORT bufsize, SSHORT* length, RemPortPtr& port); + void abort_aux_connection(); bool haveRecvData() { @@ -1022,6 +1025,7 @@ SSHORT asyncReceive(PACKET* asyncPacket, const UCHAR* buffer, SSHORT dataSize); Firebird::string getRemoteId() const; + void auxAcceptError(PACKET* packet); }; Modified: firebird/trunk/src/remote/server/server.cpp =================================================================== --- firebird/trunk/src/remote/server/server.cpp 2012-01-16 14:30:47 UTC (rev 53863) +++ firebird/trunk/src/remote/server/server.cpp 2012-01-16 15:01:17 UTC (rev 53864) @@ -1754,6 +1754,7 @@ if (aux_port) { + aux_port->port_flags |= PORT_connecting; try { if (aux_port->connect(send)) @@ -1761,11 +1762,13 @@ } catch (const Exception& ex) { + aux_port->port_flags &= ~PORT_connecting; iscLogException("", ex); fb_assert(port->port_async == aux_port); port->port_async = NULL; aux_port->disconnect(); } + aux_port->port_flags &= ~PORT_connecting; } } catch (const Exception& ex) @@ -5504,6 +5507,7 @@ switch (getOperation(buffer, dataSize)) { case op_cancel: + case op_abort_aux_connection: break; default: return 0; @@ -5530,6 +5534,12 @@ case op_cancel: cancel_operation(this, asyncPacket->p_cancel_op.p_co_kind); break; + case op_abort_aux_connection: + if (port_async && (port_async->port_flags & PORT_connecting)) + { + port_async->abort_aux_connection(); + } + break; default: return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |