diff options
38 files changed, 518 insertions, 307 deletions
diff --git a/TAO/ChangeLog b/TAO/ChangeLog index 4fe478d6494..3359481b2d7 100644 --- a/TAO/ChangeLog +++ b/TAO/ChangeLog @@ -1,4 +1,68 @@ -Mon Oct 21 21:51:07 2002 Balachandran Natarajan <bala@cs.wustl.edu> +Mon Oct 21 22:45:02 2002 Balachandran Natarajan <bala@isis-server.isis.vanderbilt.edu> + + Bug fix for [BUGID 1269]. Thanks to Carlos O'Ryan for donating + this patch. + + * tao/Connection_Handler.cpp: + * tao/Connection_Handler.h: + * tao/Connection_Handler.inl: + * tao/Connector_Impl.cpp: + * tao/IIOP_Connection_Handler.cpp: + * tao/IIOP_Connection_Handler.h: + * tao/Invocation.cpp: + * tao/LF_Connect_Strategy.cpp: + * tao/Muxed_TMS.cpp: + * tao/Notify_Handler.cpp: + * tao/Synch_Refcountable.cpp: + * tao/TAO_Server_Request.cpp: + * tao/IIOP_Connector.cpp: + * tao/IIOP_Transport.cpp: + * tao/IIOP_Transport.h: + * tao/Transport.cpp: + * tao/Transport.h: Changes to the ORB Core. The details are as + follows + + - It eliminates the two refcounts in the connection handler and + combines as one refcount. + + - The transport_ field in the Connection_Handler class is + atomically modified. + + - Closing connections are also atomic. + + - When the connection is closed all the activations in the + reactor are removed. + + For all the other gory details like the motivation for these + changes, it is advised you refer to BUGID's 1202, 1269 and + 1270. + + * tao/Strategies/DIOP_Connection_Handler.cpp: + * tao/Strategies/DIOP_Connection_Handler.h: + * tao/Strategies/DIOP_Transport.cpp: + * tao/Strategies/DIOP_Transport.h: + * tao/Strategies/SHMIOP_Connection_Handler.cpp: + * tao/Strategies/SHMIOP_Connection_Handler.h: + * tao/Strategies/SHMIOP_Transport.cpp: + * tao/Strategies/SHMIOP_Transport.h: + * tao/Strategies/UIOP_Connection_Handler.cpp: + * tao/Strategies/UIOP_Connection_Handler.h: + * tao/Strategies/UIOP_Transport.cpp: + * tao/Strategies/UIOP_Transport.h: + * orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.cpp: + * orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.h: + * orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.cpp: + * orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.h: + * orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connection_Handler.cpp: + * orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connection_Handler.h: + * orbsvcs/orbsvcs/SSLIOP/SSLIOP_Transport.cpp: + * orbsvcs/orbsvcs/SSLIOP/SSLIOP_Transport.h: + + Changes to the pluggable protocols to reflect the changes in the + ORB Core. + + +Mon Oct 21 21:51:07 2002 Balachandran Natarajan <bala@isis-server.isis.vanderbilt.edu> * tests/DLL_ORB/Makefile.Tests_Client_Module: Added TAO_ROOT definition to fix the compileation problems. diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.cpp index ef447ea3ee1..a2252e797bd 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.cpp +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.cpp @@ -221,6 +221,12 @@ TAO_UIPMC_Connection_Handler::resume_handler (void) } int +TAO_UIPMC_Connection_Handler::close_connection (void) +{ + return this->close_connection_eh (this); +} + +int TAO_UIPMC_Connection_Handler::handle_input (ACE_HANDLE h) { return this->handle_input_eh (h, this); @@ -239,12 +245,6 @@ TAO_UIPMC_Connection_Handler::handle_close (ACE_HANDLE handle, return this->handle_close_eh (handle, rm, this); } -void -TAO_UIPMC_Connection_Handler::handle_close_i (void) -{ - this->handle_close_i_eh (this); -} - int TAO_UIPMC_Connection_Handler::release_os_resources (void) { diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.h index d50a28ddba7..8f9b832a3dc 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.h +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Connection_Handler.h @@ -111,6 +111,7 @@ public: /** @name Event Handler overloads */ virtual int resume_handler (void); + virtual int close_connection (void); virtual int handle_input (ACE_HANDLE); virtual int handle_output (ACE_HANDLE); virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask); @@ -164,7 +165,6 @@ protected: /** * @name TAO_Connection Handler overloads */ - void handle_close_i (void); virtual int release_os_resources (void); //@} diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.cpp index d7e4702c92c..3829cd25b82 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.cpp +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.cpp @@ -35,6 +35,14 @@ TAO_UIPMC_Transport::TAO_UIPMC_Transport (TAO_UIPMC_Connection_Handler *handler, , connection_handler_ (handler) , messaging_object_ (0) { + if (connection_handler_ != 0) + { + // REFCNT: Matches one of + // TAO_Transport::connection_handler_close() or + // TAO_Transport::close_connection_shared. + this->connection_handler_->incr_refcount(); + } + // Use the normal GIOP object ACE_NEW (this->messaging_object_, TAO_GIOP_Message_Base (orb_core, @@ -49,8 +57,8 @@ TAO_UIPMC_Transport::TAO_UIPMC_Transport (TAO_UIPMC_Connection_Handler *handler, TAO_UIPMC_Transport::~TAO_UIPMC_Transport (void) { + ACE_ASSERT(this->connection_handler_ == 0); delete this->messaging_object_; - this->messaging_object_ = 0; } ACE_Event_Handler * @@ -544,10 +552,10 @@ TAO_UIPMC_Transport::messaging_init (CORBA::Octet major, return 1; } -ACE_Event_Handler * +TAO_Connection_Handler * TAO_UIPMC_Transport::invalidate_event_handler_i (void) { - ACE_Event_Handler * eh = this->connection_handler_; + TAO_Connection_Handler * eh = this->connection_handler_; this->connection_handler_ = 0; return eh; } diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.h index 6490d89a1b4..96467c88f8e 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.h +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Transport.h @@ -72,7 +72,7 @@ protected: virtual ACE_Event_Handler * event_handler_i (void); virtual TAO_Connection_Handler *connection_handler_i (void); - virtual ACE_Event_Handler * invalidate_event_handler_i (void); + virtual TAO_Connection_Handler * invalidate_event_handler_i (void); virtual TAO_Pluggable_Messaging *messaging_object (void); diff --git a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connection_Handler.cpp b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connection_Handler.cpp index a7705c13d0e..d6406eb84de 100644 --- a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connection_Handler.cpp +++ b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connection_Handler.cpp @@ -213,6 +213,12 @@ TAO_SSLIOP_Connection_Handler::resume_handler (void) } int +TAO_SSLIOP_Connection_Handler::close_connection (void) +{ + return this->close_connection_eh (this); +} + +int TAO_SSLIOP_Connection_Handler::handle_input (ACE_HANDLE h) { return this->handle_input_eh (h, this); @@ -231,12 +237,6 @@ TAO_SSLIOP_Connection_Handler::handle_close (ACE_HANDLE handle, return this->handle_close_eh (handle, rm, this); } -void -TAO_SSLIOP_Connection_Handler::handle_close_i (void) -{ - this->handle_close_i_eh (this); -} - int TAO_SSLIOP_Connection_Handler::release_os_resources (void) { diff --git a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connection_Handler.h b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connection_Handler.h index 0fb5a28c322..8640fa052b7 100644 --- a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connection_Handler.h +++ b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Connection_Handler.h @@ -85,6 +85,7 @@ public: /** @name Event Handler overloads */ virtual int resume_handler (void); + virtual int close_connection (void); virtual int handle_input (ACE_HANDLE); virtual int handle_output (ACE_HANDLE); virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask); @@ -112,7 +113,6 @@ protected: /** * @name TAO_Connection Handler overloads */ - void handle_close_i (void); virtual int release_os_resources (void); virtual void pos_io_hook (int & return_value); //@} diff --git a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Transport.cpp b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Transport.cpp index f5b1790033d..9e04e168a8a 100644 --- a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Transport.cpp +++ b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Transport.cpp @@ -29,6 +29,14 @@ TAO_SSLIOP_Transport::TAO_SSLIOP_Transport ( connection_handler_ (handler), messaging_object_ (0) { + if (connection_handler_ != 0) + { + // REFCNT: Matches one of + // TAO_Transport::connection_handler_close() or + // TAO_Transport::close_connection_shared. + this->connection_handler_->incr_refcount(); + } + // Use the normal GIOP object ACE_NEW (this->messaging_object_, TAO_GIOP_Message_Base (orb_core)); @@ -37,6 +45,7 @@ TAO_SSLIOP_Transport::TAO_SSLIOP_Transport ( TAO_SSLIOP_Transport::~TAO_SSLIOP_Transport (void) { + ACE_ASSERT(this->connection_handler_ == 0); delete this->messaging_object_; } @@ -402,10 +411,10 @@ TAO_SSLIOP_Transport::get_listen_point ( return 1; } -ACE_Event_Handler * +TAO_Connection_Handler * TAO_SSLIOP_Transport::invalidate_event_handler_i (void) { - ACE_Event_Handler * eh = this->connection_handler_; + TAO_Connection_Handler * eh = this->connection_handler_; this->connection_handler_ = 0; return eh; } diff --git a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Transport.h b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Transport.h index 3eee7effe6a..fb979d8798d 100644 --- a/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Transport.h +++ b/TAO/orbsvcs/orbsvcs/SSLIOP/SSLIOP_Transport.h @@ -88,7 +88,7 @@ protected: virtual ACE_Event_Handler * event_handler_i (void); virtual TAO_Connection_Handler *connection_handler_i (void); - virtual ACE_Event_Handler * invalidate_event_handler_i (void); + virtual TAO_Connection_Handler * invalidate_event_handler_i (void); virtual TAO_Pluggable_Messaging *messaging_object (void); diff --git a/TAO/tao/Connection_Handler.cpp b/TAO/tao/Connection_Handler.cpp index c75b807808e..8983deff106 100644 --- a/TAO/tao/Connection_Handler.cpp +++ b/TAO/tao/Connection_Handler.cpp @@ -22,17 +22,18 @@ ACE_RCSID (tao, "$Id$") TAO_Connection_Handler::TAO_Connection_Handler (TAO_ORB_Core *orb_core) - : orb_core_ (orb_core), - transport_ (0), - tss_resources_ (orb_core->get_tss_resources ()), - pending_upcalls_ (1), - reference_count_ (1), - pending_upcall_lock_ (0) + : orb_core_ (orb_core) + , transport_ (0) + , tss_resources_ (orb_core->get_tss_resources ()) + , reference_count_ (1) { - // NOTE: Why should the refcount be // @@todo: We need to have a distinct option/ method in the resource // factory for this and TAO_Transport. - this->pending_upcall_lock_ = + + this->refcount_lock_ = + this->orb_core_->resource_factory ()->create_cached_connection_lock (); + + this->lock_ = this->orb_core_->resource_factory ()->create_cached_connection_lock (); // Put ourselves in the connection wait state as soon as we get @@ -43,14 +44,12 @@ TAO_Connection_Handler::TAO_Connection_Handler (TAO_ORB_Core *orb_core) TAO_Connection_Handler::~TAO_Connection_Handler (void) { - // Set some of the pointers that we hold to zero explicitly, so that - // nobody tries to access these - this->orb_core_ = 0; - this->tss_resources_ = 0; - TAO_Transport::release (this->transport_); - - delete this->pending_upcall_lock_; - this->pending_upcall_lock_ = 0; + ACE_ASSERT(this->transport_ == 0); + ACE_ASSERT(this->reference_count_ == 0); + + // @@ TODO Use auto_ptr<> + delete this->lock_; + delete this->refcount_lock_; } @@ -138,13 +137,15 @@ TAO_Connection_Handler::svc_i (void) if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("TAO (%P|%t) TAO_Connection_Handler::svc_i - ") - ACE_TEXT ("loop <%d>\n"), current_timeout.msec ())); + "TAO (%P|%t) - Connection_Handler::svc_i - " + "loop <%d>\n", current_timeout.msec () + )); } if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("TAO (%P|%t) TAO_Connection_Handler::svc_i end\n"))); + "TAO (%P|%t) - Connection_Handler::svc_i end\n" + )); return result; } @@ -152,58 +153,46 @@ TAO_Connection_Handler::svc_i (void) void TAO_Connection_Handler::transport (TAO_Transport* transport) { - if (this->transport_ != 0) { - this->transport_->connection_handler_closing (); + // The transport can be reset, but not changed! + ACE_ASSERT(this->transport_ == 0 || transport == 0); + + TAO_Transport * tmp = 0; + { + // Make the change atomic + ACE_GUARD (ACE_Lock, ace_mon, *this->lock_); + tmp = this->transport_; + this->transport_ = TAO_Transport::_duplicate (transport); } - this->transport_ = TAO_Transport::_duplicate (transport); + if (tmp != 0) { + tmp->connection_handler_closing (); + TAO_Transport::release (tmp); + } } -int +long TAO_Connection_Handler::incr_refcount (void) { - ACE_GUARD_RETURN (ACE_Lock, - ace_mon, - *this->pending_upcall_lock_, -1); + ACE_GUARD_RETURN (ACE_Lock, ace_mon, *this->refcount_lock_, -1); + ACE_ASSERT(this->reference_count_ > 0); return ++this->reference_count_; } -void +long TAO_Connection_Handler::decr_refcount (void) { { - ACE_GUARD (ACE_Lock, - ace_mon, - *this->pending_upcall_lock_); + ACE_GUARD_RETURN (ACE_Lock, ace_mon, *this->refcount_lock_, -1); - --this->reference_count_; + if(--this->reference_count_ > 0) + return this->reference_count_; } - if (this->reference_count_ == 0) - this->handle_close_i (); -} - -int -TAO_Connection_Handler::incr_pending_upcalls (void) -{ - ACE_GUARD_RETURN (ACE_Lock, - ace_mon, - *this->pending_upcall_lock_, -1); - - return ++this->pending_upcalls_; - - -} - -int -TAO_Connection_Handler::decr_pending_upcalls (void) -{ - ACE_GUARD_RETURN (ACE_Lock, - ace_mon, - *this->pending_upcall_lock_, -1); + ACE_ASSERT(this->reference_count_ == 0); + delete this; - return --this->pending_upcalls_; + return 0; } int @@ -220,68 +209,23 @@ TAO_Connection_Handler::handle_close_eh ( my_handle, handle, reactor_mask)); } - if(my_handle == ACE_INVALID_HANDLE) + if (this->close_connection () == 0) { + if (TAO_debug_level) + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - IIOP_Connection_Handler[%d]::" + "handle_close, connection closing or already closed\n", + my_handle)); return 0; } - // Just close the socket irrespective of what the upcall count is, - // we need to cleanup OS resources ASAP. - this->release_os_resources (); - - // Set the handle to be INVALID_HANDLE - eh->set_handle (ACE_INVALID_HANDLE); - - this->state_changed (TAO_LF_Event::LFS_CONNECTION_CLOSED); - - // @@ TODO All this code dealing with upcalls is fishy, upcalls are - // incremented/decremented in handle_input_i(), and only - // decremented here! Also: the reference count is decremented - // here, while it is incremented in a selected few other places, - // in a very confusing ways. - long upcalls = this->decr_pending_upcalls (); - - ACE_ASSERT(upcalls >= 0); - - // If the upcall count is zero start the cleanup. - if (upcalls == 0) - this->decr_refcount (); - - return 0; -} - -void -TAO_Connection_Handler::handle_close_i_eh ( - ACE_Event_Handler * eh) -{ if (TAO_debug_level) ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - Connection_Handler[%d]::handle_close_i, " - "\n", - this->transport ()->id ())); - - if (this->transport ()->wait_strategy ()->is_registered ()) - { - // Make sure there are no timers. - ACE_ASSERT(eh->reactor() != 0); - eh->reactor ()->cancel_timer (eh); - - // Set the flag to indicate that it is no longer registered with - // the reactor, so that it isn't included in the set that is - // passed to the reactor on ORB destruction. - this->transport ()->wait_strategy ()->is_registered (0); - } - - // Close the handle.. - // Remove the entry as it is invalid - this->transport ()->purge_entry (); - - // Signal the transport that we will no longer have - // a reference to it. This will eventually call - // TAO_Transport::release (). - this->transport (0); + "TAO (%P|%t) - IIOP_Connection_Handler[%d]::" + "handle_close, connection fully closed\n", + my_handle)); - delete this; + return 0; } int @@ -297,6 +241,7 @@ TAO_Connection_Handler::handle_output_eh ( this->pre_io_hook (return_value); if (return_value != 0) { + resume_handle.set_flag (TAO_Resume_Handle::TAO_HANDLE_LEAVE_SUSPENDED); return return_value; } @@ -316,26 +261,30 @@ TAO_Connection_Handler::handle_input_eh ( ACE_HANDLE h, ACE_Event_Handler * eh) { // Increase the reference count on the upcall that have passed us. - long upcalls = this->incr_pending_upcalls (); + // + // REFCNT: Matches decr_refcount() in this function... + long refcount = this->incr_refcount (); + ACE_ASSERT (refcount > 0); if (TAO_debug_level > 6) { ACE_HANDLE handle = eh->get_handle(); ACE_DEBUG ((LM_DEBUG, "TAO (%P|%t) - IIOP_Connection_Handler[%d]::handle_input, " - "handle = %d/%d, upcalls = %d\n", - this->transport()->id(), handle, h, upcalls)); + "handle = %d/%d, refcount = %d\n", + this->transport()->id(), handle, h, refcount)); } - ACE_ASSERT (upcalls > 0); - TAO_Resume_Handle resume_handle (this->orb_core (), - eh->get_handle ()); + TAO_Resume_Handle resume_handle (this->orb_core (), eh->get_handle ()); int return_value = 0; this->pre_io_hook (return_value); if (return_value != 0) { + // REFCNT: Matches incr_refcount() at the beginning... + refcount = this->decr_refcount (); + ACE_ASSERT (refcount >= 0); return return_value; } @@ -343,30 +292,20 @@ TAO_Connection_Handler::handle_input_eh ( this->pos_io_hook(return_value); - // The upcall is done. Bump down the reference count - upcalls = this->decr_pending_upcalls (); + // REFCNT: Matches incr_refcount() at the beginning... + refcount = this->decr_refcount (); + ACE_ASSERT (refcount >= 0); if (TAO_debug_level > 6) { ACE_HANDLE handle = eh->get_handle(); ACE_DEBUG ((LM_DEBUG, "TAO (%P|%t) - IIOP_Connection_Handler[%d]::handle_input, " - "handle = %d/%d, upcalls = %d, retval = %d\n", - this->transport()->id(), handle, h, upcalls, return_value)); - } - ACE_ASSERT (upcalls >= 0); - - if (upcalls == 0) - { - this->decr_refcount (); - - // As we have already performed the handle closing (indirectly) - // we dont want to return a -1. Doing so would make the reactor - // call handle_close () which could be harmful. - return_value = 0; + "handle = %d/%d, refcount = %d, retval = %d\n", + this->transport()->id(), handle, h, refcount, return_value)); } - if (return_value != 0 || upcalls == 0) + if (return_value == -1 || refcount == 0) { // This is really a odd case. We could have a race condition if // we dont do this. Looks like this what happens @@ -393,6 +332,162 @@ TAO_Connection_Handler::handle_input_eh ( } int +TAO_Connection_Handler::close_connection_eh (ACE_Event_Handler * eh) +{ + // Perform a double checked locking on the underlying ACE_HANDLE + ACE_HANDLE handle = eh->get_handle(); + + // If the handle is ACE_INVALID_HANDLE then there is no work to be + // done in this function, and we return immediately. Returning 0 + // indicates the caller (handle_close() most likely), that there is + // no work to be done. + if (handle == ACE_INVALID_HANDLE) + { + return 0; + } + + int id = -1; + { + ACE_GUARD_RETURN(ACE_Lock, ace_mon, *this->lock_, 0); + + handle = eh->get_handle(); + if(handle == ACE_INVALID_HANDLE) + { + return 0; + } + + // Before closing the socket we need to remove ourselves from the + // Reactor. Sounds silly, as supposedly handle_close() was called + // *BY* the Reactor, but the Reactor calls handle_close() with + // only the masks implied by the handle_XXX() call that returned + // -1, and it does *NOT* remove the Event Handler from all masks. + // Furthermore, this method is also called outside the Reactor + // event loop, for example, when an I/O error is detected during a + // write(). + + // The following assertion is true because: + // + // + // 1) When a connection handler is initialized Transport is not zero + // and the handle is *NOT* ACE_INVALID_HANDLE. + // 2) The code here is run only once, if we get to this point the + // handle was not ACE_INVALID_HANDLE + // 3) this->transport() is only reset after we run this code + // successfully + // + // Or: for this code to run the handle must have changed state from + // something valid to ACE_INVALID_HANDLE, and the transport() field + // will not be changed before that state transition. + // + ACE_ASSERT(this->transport () != 0); + + // Save the ID for debugging messages + id = this->transport()->id(); + if (TAO_debug_level) + { + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - Connection_Handler[%d]::" + "close_connection, purging entry from cache\n", + id)); + } + this->transport ()->purge_entry (); + + // The Reactor must not be null, otherwise something else is + // horribly broken. + ACE_Reactor * reactor = this->transport()->orb_core()->reactor (); + ACE_ASSERT(reactor != 0); + + { + ACE_Reactor * orb_core_reactor = this->orb_core_->reactor (); + ACE_ASSERT(reactor == orb_core_reactor); + + ACE_Reactor * eh_reactor = eh->reactor (); + ACE_ASSERT(eh_reactor == 0 || eh_reactor == reactor); + } + + if (TAO_debug_level) + { + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - Connection_Handler[%d]::" + "close_connection, removing from the reactor\n", + id)); + } + int r = + reactor->remove_handler (handle, + (ACE_Event_Handler::ALL_EVENTS_MASK + | ACE_Event_Handler::DONT_CALL)); + if(r == -1 && TAO_debug_level) + { + ACE_ERROR ((LM_ERROR, + "TAO (%P|%t) - Connection_Handler[%d]::" + "close_connection, error in remove_handler (%d)\n", + id, r)); + } + + // Also cancel any timers, we may create those for time-limited + // buffering + if (TAO_debug_level) + { + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - Connection_Handler[%d]::" + "close_connection, cancel all timers\n", + id)); + } + r = reactor->cancel_timer (eh); + if (r == -1 && TAO_debug_level) + { + ACE_ERROR ((LM_ERROR, + "TAO (%P|%t) - Connection_Handler[%d]::" + "close_connection, error cancelling timers\n", + id)); + } + + // @@ This seems silly, the reactor is a much better authority to + // find out if a handle is registered... + this->transport ()->wait_strategy ()->is_registered (0); + + // Close the socket, implicitly this makes: + // get_handle() == ACE_INVALID_HANDLE + // At this point any further calls to handle_close() or + // close_connection() become no-ops + r = this->release_os_resources (); + if (r == -1 && TAO_debug_level) + { + ACE_ERROR ((LM_ERROR, + "TAO (%P|%t) - Connection_Handler[%d]::" + "close_connection, release_os_resources() failed %p\n", + id, "")); + } + + ACE_ASSERT(eh->get_handle() == ACE_INVALID_HANDLE); + } + + ACE_ASSERT(this->transport () != 0); + + this->state_changed (TAO_LF_Event::LFS_CONNECTION_CLOSED); + + // Signal the transport that we will no longer have + // a reference to it. This will eventually call + // TAO_Transport::release (). + this->transport (0); + + // The Reactor (or the Connector) holds an implicit reference. + // REFCNT: Matches start count + // REFCNT: only this or handle_input_eh() are called + long refcount = this->decr_refcount (); + + if (TAO_debug_level) + { + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - Connection_Handler[%d]::" + "close_connection, refcount = %d\n", + id, refcount)); + } + + return 1; +} + +int TAO_Connection_Handler::release_os_resources (void) { return 0; diff --git a/TAO/tao/Connection_Handler.h b/TAO/tao/Connection_Handler.h index 43724480e2e..c72d1c92c6f 100644 --- a/TAO/tao/Connection_Handler.h +++ b/TAO/tao/Connection_Handler.h @@ -69,8 +69,19 @@ public: /// Increment and decrement the refcount. The object is deleted when /// the refcount reaches zero. - int incr_refcount (void); - void decr_refcount (void); + long incr_refcount (void); + long decr_refcount (void); + + /// Close the underlying connection. + /** + * Used by the ORB to actively close connections that are idle, + * stale or somehow are determined to be broken before the Reactor + * does. + * + * @return Return 0 if the connection was already closed, non-zero + * otherwise. + */ + virtual int close_connection (void) = 0; /// The event handler calls, here so that other objects who hold a /// reference to this object can call the event handler methods. @@ -103,9 +114,6 @@ protected: /// Query the upcall count int pending_upcalls (void) const; - /// Shutdown the object - virtual void handle_close_i (void) = 0; - //@{ /** * @name Helper methods for Event_Handler-based derived classes. @@ -122,16 +130,18 @@ protected: unsigned long reactor_mask, ACE_Event_Handler * eh); - /// Implement the handle_close_i() template method. - void handle_close_i_eh (ACE_Event_Handler * eh); - /// Implement the handle_output() callback int handle_output_eh (ACE_HANDLE h, ACE_Event_Handler * eh); /// Implement the handle_input() callback int handle_input_eh (ACE_HANDLE h, ACE_Event_Handler * eh); - /// Release the OS resources related to this handler, used in handle_close_eh() + /// Implement close_connection() for Connection_Handlers that are + /// also Event_Handlers. + int close_connection_eh (ACE_Event_Handler * eh); + + /// Release the OS resources related to this handler, used in + /// handle_close_eh() virtual int release_os_resources (void); /// Pre-invocation hook for I/O operations (handle_input() & @@ -159,25 +169,15 @@ private: /// Cached tss resources of the ORB that activated this object. TAO_ORB_Core_TSS_Resources *tss_resources_; - /// Count nested upcalls on this - /// svc_handler i.e., the connection can close during nested upcalls, - /// you should not delete the svc_handler until the stack unwinds - /// from the nested upcalls. - long pending_upcalls_; - - /* Have a count of the number of references to the - * handler. Theoretically this should be in the reactor. As we dont - * have this in the reactor we are providing it here. - * - * NOTE: Please dont try to combine this with the pending - * upcalls. They are for two completely different things. - * @@todo: Need to be moved into the reactor at a later date - */ + /// Pretty obvious long reference_count_; - /// Lock for the <pending_upcalls_>. We can have more than one - /// thread trying to access. - ACE_Lock *pending_upcall_lock_; + /// Lock for the reference count + ACE_Lock *refcount_lock_; + + /// Internal state lock, needs to be separate from the reference + /// count / pending upcalls lock because they interleave. + ACE_Lock * lock_; }; #if defined (__ACE_INLINE__) diff --git a/TAO/tao/Connection_Handler.inl b/TAO/tao/Connection_Handler.inl index 0b8117b0b9c..5c1df839f72 100644 --- a/TAO/tao/Connection_Handler.inl +++ b/TAO/tao/Connection_Handler.inl @@ -2,16 +2,6 @@ // //$Id$ -ACE_INLINE -TAO_Connection_Handler::TAO_Connection_Handler (void) - : orb_core_ (0), - transport_ (0), - tss_resources_ (0), - pending_upcalls_ (1), - pending_upcall_lock_ (0) -{ -} - ACE_INLINE TAO_ORB_Core * TAO_Connection_Handler::orb_core (void) { @@ -33,8 +23,7 @@ TAO_Connection_Handler::transport (void) ACE_INLINE int TAO_Connection_Handler::is_connect_complete (void) const { - return this->successful () || - this->error_detected (); + return this->successful () || this->error_detected (); } ACE_INLINE int @@ -42,9 +31,3 @@ TAO_Connection_Handler::is_connect_successful (void) const { return (this->error_detected () == 0); } - -ACE_INLINE int -TAO_Connection_Handler::pending_upcalls (void) const -{ - return this->pending_upcalls_; -} diff --git a/TAO/tao/Connector_Impl.cpp b/TAO/tao/Connector_Impl.cpp index 757a511d2ae..a4bb4cee8c0 100644 --- a/TAO/tao/Connector_Impl.cpp +++ b/TAO/tao/Connector_Impl.cpp @@ -42,6 +42,8 @@ TAO_Connect_Creation_Strategy<SVC_HANDLER>::make_svc_handler (SVC_HANDLER *&sh) // Add a reference count. Why is this needed? We need this to make // sure that the connector doesnt delete this handler when we are // waiting for non-blocking connects to complete. + + // REFCNT: matches decr_refcount() in XXX_Connector::make_connection() sh->incr_refcount (); return 0; diff --git a/TAO/tao/IIOP_Connection_Handler.cpp b/TAO/tao/IIOP_Connection_Handler.cpp index 53702a5db48..50fccb14468 100644 --- a/TAO/tao/IIOP_Connection_Handler.cpp +++ b/TAO/tao/IIOP_Connection_Handler.cpp @@ -196,6 +196,12 @@ TAO_IIOP_Connection_Handler::resume_handler (void) } int +TAO_IIOP_Connection_Handler::close_connection (void) +{ + return this->close_connection_eh (this); +} + +int TAO_IIOP_Connection_Handler::handle_input (ACE_HANDLE h) { return this->handle_input_eh (h, this); @@ -214,12 +220,6 @@ TAO_IIOP_Connection_Handler::handle_close (ACE_HANDLE handle, return this->handle_close_eh (handle, rm, this); } -void -TAO_IIOP_Connection_Handler::handle_close_i (void) -{ - this->handle_close_i_eh (this); -} - int TAO_IIOP_Connection_Handler::release_os_resources (void) { diff --git a/TAO/tao/IIOP_Connection_Handler.h b/TAO/tao/IIOP_Connection_Handler.h index 4f626c49bcb..2868103c8d8 100644 --- a/TAO/tao/IIOP_Connection_Handler.h +++ b/TAO/tao/IIOP_Connection_Handler.h @@ -112,6 +112,7 @@ public: /** @name Event Handler overloads */ virtual int resume_handler (void); + virtual int close_connection (void); virtual int handle_input (ACE_HANDLE); virtual int handle_output (ACE_HANDLE); virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask); @@ -144,7 +145,6 @@ protected: /** * @name TAO_Connection Handler overloads */ - void handle_close_i (void); virtual int release_os_resources (void); //@} diff --git a/TAO/tao/IIOP_Connector.cpp b/TAO/tao/IIOP_Connector.cpp index c76a1d6987e..fcbdfe29e52 100644 --- a/TAO/tao/IIOP_Connector.cpp +++ b/TAO/tao/IIOP_Connector.cpp @@ -202,6 +202,8 @@ TAO_IIOP_Connector::make_connection (TAO_GIOP_Invocation *invocation, // increment to the handler is done in make_svc_handler (). Now // that we dont need the reference to it anymore we can decrement // the refcount whether the connection is successful ot not. + + // REFCNT: Matches with TAO_Connect_Strategy<>::make_svc_handler() svc_handler->decr_refcount (); if (result == -1) diff --git a/TAO/tao/IIOP_Transport.cpp b/TAO/tao/IIOP_Transport.cpp index 839eff992d1..3b0e521da54 100644 --- a/TAO/tao/IIOP_Transport.cpp +++ b/TAO/tao/IIOP_Transport.cpp @@ -36,6 +36,13 @@ TAO_IIOP_Transport::TAO_IIOP_Transport (TAO_IIOP_Connection_Handler *handler, , connection_handler_ (handler) , messaging_object_ (0) { + if (connection_handler_ != 0) + { + // REFCNT: Matches one of + // TAO_Transport::connection_handler_close() or + // TAO_Transport::close_connection_shared. + this->connection_handler_->incr_refcount(); + } if (flag) { // Use the lite version of the protocol @@ -51,8 +58,8 @@ TAO_IIOP_Transport::TAO_IIOP_Transport (TAO_IIOP_Connection_Handler *handler, } TAO_IIOP_Transport::~TAO_IIOP_Transport (void) - { + ACE_ASSERT(this->connection_handler_ == 0); delete this->messaging_object_; } @@ -449,10 +456,10 @@ TAO_IIOP_Transport::get_listen_point ( return 1; } -ACE_Event_Handler * +TAO_Connection_Handler * TAO_IIOP_Transport::invalidate_event_handler_i (void) { - ACE_Event_Handler * eh = this->connection_handler_; + TAO_Connection_Handler * eh = this->connection_handler_; this->connection_handler_ = 0; return eh; } diff --git a/TAO/tao/IIOP_Transport.h b/TAO/tao/IIOP_Transport.h index 5c77d336d66..ede1267e165 100644 --- a/TAO/tao/IIOP_Transport.h +++ b/TAO/tao/IIOP_Transport.h @@ -75,7 +75,7 @@ protected: //@{ virtual ACE_Event_Handler * event_handler_i (void); - virtual ACE_Event_Handler * invalidate_event_handler_i (void); + virtual TAO_Connection_Handler * invalidate_event_handler_i (void); /// Access the underlying messaging object virtual TAO_Pluggable_Messaging *messaging_object (void); diff --git a/TAO/tao/Invocation.cpp b/TAO/tao/Invocation.cpp index 2459e750f00..c48ddbe44d2 100644 --- a/TAO/tao/Invocation.cpp +++ b/TAO/tao/Invocation.cpp @@ -99,6 +99,9 @@ TAO_GIOP_Invocation::TAO_GIOP_Invocation (void) received_location_forward_ (0), profile_index_ (0) { +#if defined (ACE_HAS_PURIFY) + ACE_OS::memset(buffer_, 0, sizeof(buffer_)); +#endif /* ACE_HAS_PURIFY */ } TAO_GIOP_Invocation::TAO_GIOP_Invocation (TAO_Stub *stub, @@ -134,6 +137,9 @@ TAO_GIOP_Invocation::TAO_GIOP_Invocation (TAO_Stub *stub, received_location_forward_ (0), profile_index_ (0) { +#if defined (ACE_HAS_PURIFY) + ACE_OS::memset(buffer_, 0, sizeof(buffer_)); +#endif /* ACE_HAS_PURIFY */ } TAO_GIOP_Invocation::~TAO_GIOP_Invocation (void) diff --git a/TAO/tao/LF_Connect_Strategy.cpp b/TAO/tao/LF_Connect_Strategy.cpp index 83ce6483ed1..e20cc3b3aa0 100644 --- a/TAO/tao/LF_Connect_Strategy.cpp +++ b/TAO/tao/LF_Connect_Strategy.cpp @@ -45,15 +45,26 @@ int TAO_LF_Connect_Strategy::wait (TAO_Connection_Handler *ch, ACE_Time_Value *max_wait_time) { - TAO_Transport *transport = - ch->transport (); + ACE_ASSERT(ch != 0); + + // @@todo We need to use a auto_ptr<>-like object here! + // TAO_Transport * transport = ch->get_transport_locked(); + TAO_Transport *transport = ch->transport (); + + // Basically the connection was EINPROGRESS, but before we could + // wait for it some other thread detected a failure and cleaned up + // the connection handler. + if(transport == 0) + { + return -1; + } if (TAO_debug_level > 2) { ACE_DEBUG ((LM_DEBUG, "TAO (%P|%t) - LF_Connect_Strategy::wait, " "waiting for Transport[%d]\n", - transport->id())); + transport->id ())); } TAO_Leader_Follower &leader_follower = @@ -76,5 +87,8 @@ TAO_LF_Connect_Strategy::wait (TAO_Connection_Handler *ch, transport->id(), result)); } + // @@todo We need to use a auto_ptr<>-like object here! + // TAO_Transport::release(transport); + return result; } diff --git a/TAO/tao/Muxed_TMS.cpp b/TAO/tao/Muxed_TMS.cpp index 88d7207d0e7..5f9a12bff1e 100644 --- a/TAO/tao/Muxed_TMS.cpp +++ b/TAO/tao/Muxed_TMS.cpp @@ -48,7 +48,8 @@ TAO_Muxed_TMS::request_id (void) if (TAO_debug_level > 4) ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("(%P|%t) TAO_Muxed_TMS::request_id - <%d>\n"), + "TAO (%P|%t) - Muxed_TMS[%d]::request_id, <%d>\n", + this->transport_->id (), this->request_id_generator_)); return this->request_id_generator_; diff --git a/TAO/tao/Notify_Handler.cpp b/TAO/tao/Notify_Handler.cpp index cb3b6391740..428644e2f34 100644 --- a/TAO/tao/Notify_Handler.cpp +++ b/TAO/tao/Notify_Handler.cpp @@ -8,8 +8,19 @@ ACE_RCSID (tao, Notify_Handler, "$Id$") +TAO_Notify_Handler::TAO_Notify_Handler (TAO_Connection_Handler *ch, + ACE_Allocator *alloc) + : ACE_Event_Handler (ch->transport ()->orb_core ()->reactor ()), + ch_ (ch), + allocator_ (alloc) +{ + // REFCNT: Matches with Notify_Handler::~Notify_Handler() + this->ch_->incr_refcount (); +} + TAO_Notify_Handler::~TAO_Notify_Handler (void) { + // REFCNT: Matches with Notify_Handler::Notify_Handler() this->ch_->decr_refcount (); } @@ -69,13 +80,3 @@ TAO_Notify_Handler::handle_close (ACE_HANDLE /*fd*/, TAO_Notify_Handler::destroy_handler (this); return 0; } - - -TAO_Notify_Handler::TAO_Notify_Handler (TAO_Connection_Handler *ch, - ACE_Allocator *alloc) - : ACE_Event_Handler (ch->transport ()->orb_core ()->reactor ()), - ch_ (ch), - allocator_ (alloc) -{ - this->ch_->incr_refcount (); -} diff --git a/TAO/tao/Strategies/DIOP_Connection_Handler.cpp b/TAO/tao/Strategies/DIOP_Connection_Handler.cpp index 7eff396e38a..5dbad7978d5 100644 --- a/TAO/tao/Strategies/DIOP_Connection_Handler.cpp +++ b/TAO/tao/Strategies/DIOP_Connection_Handler.cpp @@ -208,6 +208,12 @@ TAO_DIOP_Connection_Handler::resume_handler (void) } int +TAO_DIOP_Connection_Handler::close_connection (void) +{ + return this->close_connection_eh (this); +} + +int TAO_DIOP_Connection_Handler::handle_input (ACE_HANDLE h) { return this->handle_input_eh (h, this); @@ -226,12 +232,6 @@ TAO_DIOP_Connection_Handler::handle_close (ACE_HANDLE handle, return this->handle_close_eh (handle, rm, this); } -void -TAO_DIOP_Connection_Handler::handle_close_i (void) -{ - this->handle_close_i_eh (this); -} - int TAO_DIOP_Connection_Handler::release_os_resources (void) { diff --git a/TAO/tao/Strategies/DIOP_Connection_Handler.h b/TAO/tao/Strategies/DIOP_Connection_Handler.h index 861ee92bec5..7a021b3cee0 100644 --- a/TAO/tao/Strategies/DIOP_Connection_Handler.h +++ b/TAO/tao/Strategies/DIOP_Connection_Handler.h @@ -115,6 +115,7 @@ public: /** @name Event Handler overloads */ virtual int resume_handler (void); + virtual int close_connection (void); virtual int handle_input (ACE_HANDLE); virtual int handle_output (ACE_HANDLE); virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask); @@ -159,7 +160,6 @@ protected: /** * @name TAO_Connection Handler overloads */ - void handle_close_i (void); virtual int release_os_resources (void); //@} diff --git a/TAO/tao/Strategies/DIOP_Transport.cpp b/TAO/tao/Strategies/DIOP_Transport.cpp index 3047e157f95..82274b7cec7 100644 --- a/TAO/tao/Strategies/DIOP_Transport.cpp +++ b/TAO/tao/Strategies/DIOP_Transport.cpp @@ -36,6 +36,13 @@ TAO_DIOP_Transport::TAO_DIOP_Transport (TAO_DIOP_Connection_Handler *handler, , connection_handler_ (handler) , messaging_object_ (0) { + if (connection_handler_ != 0) + { + // REFCNT: Matches one of + // TAO_Transport::connection_handler_close() or + // TAO_Transport::close_connection_shared. + this->connection_handler_->incr_refcount(); + } // @@ Michael: Set the input CDR size to ACE_MAX_DGRAM_SIZE so that // we read the whole UDP packet on a single read. if (flag) @@ -56,6 +63,7 @@ TAO_DIOP_Transport::TAO_DIOP_Transport (TAO_DIOP_Connection_Handler *handler, TAO_DIOP_Transport::~TAO_DIOP_Transport (void) { + ACE_ASSERT(this->connection_handler_ == 0); delete this->messaging_object_; } @@ -470,10 +478,10 @@ TAO_DIOP_Transport::get_listen_point ( } */ -ACE_Event_Handler * +TAO_Connection_Handler * TAO_DIOP_Transport::invalidate_event_handler_i (void) { - ACE_Event_Handler * eh = this->connection_handler_; + TAO_Connection_Handler * eh = this->connection_handler_; this->connection_handler_ = 0; return eh; } diff --git a/TAO/tao/Strategies/DIOP_Transport.h b/TAO/tao/Strategies/DIOP_Transport.h index 7c42929342b..c47c60d1a93 100644 --- a/TAO/tao/Strategies/DIOP_Transport.h +++ b/TAO/tao/Strategies/DIOP_Transport.h @@ -75,7 +75,7 @@ protected: virtual ACE_Event_Handler * event_handler_i (void); virtual TAO_Connection_Handler *connection_handler_i (void); - virtual ACE_Event_Handler * invalidate_event_handler_i (void); + virtual TAO_Connection_Handler * invalidate_event_handler_i (void); virtual TAO_Pluggable_Messaging *messaging_object (void); /// Write the complete Message_Block chain to the connection. diff --git a/TAO/tao/Strategies/SHMIOP_Connection_Handler.cpp b/TAO/tao/Strategies/SHMIOP_Connection_Handler.cpp index 4fc91e75f87..a419525fd1e 100644 --- a/TAO/tao/Strategies/SHMIOP_Connection_Handler.cpp +++ b/TAO/tao/Strategies/SHMIOP_Connection_Handler.cpp @@ -169,6 +169,12 @@ TAO_SHMIOP_Connection_Handler::resume_handler (void) } int +TAO_SHMIOP_Connection_Handler::close_connection (void) +{ + return this->close_connection_eh (this); +} + +int TAO_SHMIOP_Connection_Handler::handle_input (ACE_HANDLE h) { return this->handle_input_eh (h, this); @@ -187,12 +193,6 @@ TAO_SHMIOP_Connection_Handler::handle_close (ACE_HANDLE handle, return this->handle_close_eh (handle, rm, this); } -void -TAO_SHMIOP_Connection_Handler::handle_close_i (void) -{ - this->handle_close_i_eh (this); -} - int TAO_SHMIOP_Connection_Handler::release_os_resources (void) { diff --git a/TAO/tao/Strategies/SHMIOP_Connection_Handler.h b/TAO/tao/Strategies/SHMIOP_Connection_Handler.h index 863ddeefeca..6995d830a25 100644 --- a/TAO/tao/Strategies/SHMIOP_Connection_Handler.h +++ b/TAO/tao/Strategies/SHMIOP_Connection_Handler.h @@ -85,6 +85,7 @@ public: /** @name Event Handler overloads */ virtual int resume_handler (void); + virtual int close_connection (void); virtual int handle_input (ACE_HANDLE); virtual int handle_output (ACE_HANDLE); virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask); @@ -99,7 +100,6 @@ protected: /** * @name TAO_Connection Handler overloads */ - void handle_close_i (void); virtual int release_os_resources (void); //@} diff --git a/TAO/tao/Strategies/SHMIOP_Transport.cpp b/TAO/tao/Strategies/SHMIOP_Transport.cpp index 521291088da..7ce4130fa5b 100644 --- a/TAO/tao/Strategies/SHMIOP_Transport.cpp +++ b/TAO/tao/Strategies/SHMIOP_Transport.cpp @@ -34,6 +34,13 @@ TAO_SHMIOP_Transport::TAO_SHMIOP_Transport (TAO_SHMIOP_Connection_Handler *handl connection_handler_ (handler), messaging_object_ (0) { + if (connection_handler_ != 0) + { + // REFCNT: Matches one of + // TAO_Transport::connection_handler_close() or + // TAO_Transport::close_connection_shared. + this->connection_handler_->incr_refcount(); + } if (flag) { // Use the lite version of the protocol @@ -50,6 +57,7 @@ TAO_SHMIOP_Transport::TAO_SHMIOP_Transport (TAO_SHMIOP_Connection_Handler *handl TAO_SHMIOP_Transport::~TAO_SHMIOP_Transport (void) { + ACE_ASSERT(this->connection_handler_ == 0); delete this->messaging_object_; } @@ -281,10 +289,10 @@ TAO_SHMIOP_Transport::messaging_init (CORBA::Octet major, return 1; } -ACE_Event_Handler * +TAO_Connection_Handler * TAO_SHMIOP_Transport::invalidate_event_handler_i (void) { - ACE_Event_Handler * eh = this->connection_handler_; + TAO_Connection_Handler * eh = this->connection_handler_; this->connection_handler_ = 0; return eh; } diff --git a/TAO/tao/Strategies/SHMIOP_Transport.h b/TAO/tao/Strategies/SHMIOP_Transport.h index 21430b34000..b41197303ae 100644 --- a/TAO/tao/Strategies/SHMIOP_Transport.h +++ b/TAO/tao/Strategies/SHMIOP_Transport.h @@ -69,8 +69,7 @@ protected: //@{ virtual ACE_Event_Handler * event_handler_i (void); virtual TAO_Connection_Handler *connection_handler_i (void); - virtual ACE_Event_Handler * invalidate_event_handler_i (void); - + virtual TAO_Connection_Handler * invalidate_event_handler_i (void); virtual TAO_Pluggable_Messaging *messaging_object (void); /// Write the complete Message_Block chain to the connection. diff --git a/TAO/tao/Strategies/UIOP_Connection_Handler.cpp b/TAO/tao/Strategies/UIOP_Connection_Handler.cpp index 8093f178a7d..51e02d17761 100644 --- a/TAO/tao/Strategies/UIOP_Connection_Handler.cpp +++ b/TAO/tao/Strategies/UIOP_Connection_Handler.cpp @@ -152,6 +152,12 @@ TAO_UIOP_Connection_Handler::resume_handler (void) } int +TAO_UIOP_Connection_Handler::close_connection (void) +{ + return this->close_connection_eh (this); +} + +int TAO_UIOP_Connection_Handler::handle_input (ACE_HANDLE h) { return this->handle_input_eh (h, this); @@ -170,12 +176,6 @@ TAO_UIOP_Connection_Handler::handle_close (ACE_HANDLE handle, return this->handle_close_eh (handle, rm, this); } -void -TAO_UIOP_Connection_Handler::handle_close_i (void) -{ - this->handle_close_i_eh (this); -} - int TAO_UIOP_Connection_Handler::release_os_resources (void) { diff --git a/TAO/tao/Strategies/UIOP_Connection_Handler.h b/TAO/tao/Strategies/UIOP_Connection_Handler.h index bb1eb7ee2af..4a86e13dd64 100644 --- a/TAO/tao/Strategies/UIOP_Connection_Handler.h +++ b/TAO/tao/Strategies/UIOP_Connection_Handler.h @@ -104,6 +104,7 @@ public: /** @name Event Handler overloads */ virtual int resume_handler (void); + virtual int close_connection (void); virtual int handle_input (ACE_HANDLE); virtual int handle_output (ACE_HANDLE); virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask); @@ -118,7 +119,6 @@ protected: /** * @name TAO_Connection Handler overloads */ - void handle_close_i (void); virtual int release_os_resources (void); //@} diff --git a/TAO/tao/Strategies/UIOP_Transport.cpp b/TAO/tao/Strategies/UIOP_Transport.cpp index 46056bcbe8a..14823585184 100644 --- a/TAO/tao/Strategies/UIOP_Transport.cpp +++ b/TAO/tao/Strategies/UIOP_Transport.cpp @@ -33,6 +33,13 @@ TAO_UIOP_Transport::TAO_UIOP_Transport (TAO_UIOP_Connection_Handler *handler, , connection_handler_ (handler) , messaging_object_ (0) { + if (connection_handler_ != 0) + { + // REFCNT: Matches one of + // TAO_Transport::connection_handler_close() or + // TAO_Transport::close_connection_shared. + this->connection_handler_->incr_refcount(); + } if (flag) { // Use the lite version of the protocol @@ -49,6 +56,7 @@ TAO_UIOP_Transport::TAO_UIOP_Transport (TAO_UIOP_Connection_Handler *handler, TAO_UIOP_Transport::~TAO_UIOP_Transport (void) { + ACE_ASSERT(this->connection_handler_ == 0); delete this->messaging_object_; } @@ -211,10 +219,10 @@ TAO_UIOP_Transport::messaging_init (CORBA::Octet major, return 1; } -ACE_Event_Handler * +TAO_Connection_Handler * TAO_UIOP_Transport::invalidate_event_handler_i (void) { - ACE_Event_Handler * eh = this->connection_handler_; + TAO_Connection_Handler * eh = this->connection_handler_; this->connection_handler_ = 0; return eh; } diff --git a/TAO/tao/Strategies/UIOP_Transport.h b/TAO/tao/Strategies/UIOP_Transport.h index 082bd31e7b6..cb504621570 100644 --- a/TAO/tao/Strategies/UIOP_Transport.h +++ b/TAO/tao/Strategies/UIOP_Transport.h @@ -68,8 +68,7 @@ protected: virtual ACE_Event_Handler * event_handler_i (void); virtual TAO_Connection_Handler *connection_handler_i (void); - virtual ACE_Event_Handler * invalidate_event_handler_i (void); - + virtual TAO_Connection_Handler * invalidate_event_handler_i (void); virtual TAO_Pluggable_Messaging *messaging_object (void); /// Write the complete Message_Block chain to the connection. diff --git a/TAO/tao/Synch_Refcountable.cpp b/TAO/tao/Synch_Refcountable.cpp index 4bd6b1fc0ab..05f2a835ad1 100644 --- a/TAO/tao/Synch_Refcountable.cpp +++ b/TAO/tao/Synch_Refcountable.cpp @@ -18,5 +18,6 @@ TAO_Synch_Refcountable::TAO_Synch_Refcountable (ACE_Lock *lock, TAO_Synch_Refcountable::~TAO_Synch_Refcountable (void) { + ACE_ASSERT(this->refcount_ == 0); delete this->refcount_lock_; } diff --git a/TAO/tao/TAO_Server_Request.cpp b/TAO/tao/TAO_Server_Request.cpp index c4b8c4a7759..2dd24445b54 100644 --- a/TAO/tao/TAO_Server_Request.cpp +++ b/TAO/tao/TAO_Server_Request.cpp @@ -278,7 +278,7 @@ TAO_ServerRequest::tao_send_reply_exception (CORBA::Exception &ex) // Create a new output CDR stream -# if 0 +#if 0 #if defined(ACE_HAS_PURIFY) // Only inititialize the buffer if we're compiling with Purify. // Otherwise, there is no real need to do so, especially since @@ -288,8 +288,6 @@ TAO_ServerRequest::tao_send_reply_exception (CORBA::Exception &ex) #else char repbuf[ACE_CDR::DEFAULT_BUFSIZE]; #endif /* ACE_HAS_PURIFY */ -#endif /*if 0*/ - /* TAO_OutputCDR output (repbuf, sizeof repbuf, TAO_ENCAP_BYTE_ORDER, @@ -301,6 +299,7 @@ TAO_ServerRequest::tao_send_reply_exception (CORBA::Exception &ex) TAO_DEF_GIOP_MINOR, this->orb_core_->to_iso8859 (), this->orb_core_->to_unicode ());*/ +#endif /* 0 */ // Make the reply message if (this->mesg_base_->generate_exception_reply (*this->outgoing_, diff --git a/TAO/tao/Transport.cpp b/TAO/tao/Transport.cpp index e2859142b3d..a6a0bc92830 100644 --- a/TAO/tao/Transport.cpp +++ b/TAO/tao/Transport.cpp @@ -126,25 +126,18 @@ TAO_Transport::TAO_Transport (CORBA::ULong tag, TAO_Transport::~TAO_Transport (void) { + ACE_ASSERT(this->refcount() == 0); + delete this->ws_; - this->ws_ = 0; delete this->tms_; - this->tms_ = 0; delete this->handler_lock_; - while (this->head_ != 0) - { - TAO_Queued_Message *i = this->head_; - this->head_ = i->next (); - i->destroy (); - } - - // Avoid making the call if we can. This may be redundant, unless - // someone called handle_close() on the connection handler from - // outside the TAO_Transport. - this->transport_cache_manager ().purge_entry (this->cache_map_entry_); + // By the time the destructor is reached all the connection stuff + // *must* have been cleaned up + ACE_ASSERT(this->head_ == 0); + ACE_ASSERT(this->cache_map_entry_ == 0); } @@ -280,7 +273,7 @@ TAO_Transport::tear_listen_point_list (TAO_InputCDR &) void TAO_Transport::close_connection (void) { - ACE_Event_Handler * eh = this->invalidate_event_handler (); + TAO_Connection_Handler * eh = this->invalidate_event_handler (); this->close_connection_shared (1, eh); } @@ -344,12 +337,15 @@ TAO_Transport::connection_handler_closing (void) // error. Basically all the other methods in the Transport // cooperate via check_event_handler_i() - (void) this->invalidate_event_handler (); + TAO_Connection_Handler * eh = this->invalidate_event_handler (); this->send_connection_closed_notifications (); - // Can't hold the lock while we release, b/c the release could - // invoke the destructor! This should be the last thing we do here - TAO_Transport::release (this); + if (eh != 0) + { + // REFCNT: Matches incr_refcnt in XXX_Transport::XXX_Transport + // REFCNT: Only one of this or close_connection_shared() run + eh->decr_refcount(); + } } int @@ -669,21 +665,20 @@ TAO_Transport::send_synch_message_helper_i (TAO_Synch_Queued_Message &synch_mess void TAO_Transport::close_connection_i (void) { - ACE_Event_Handler * eh = this->invalidate_event_handler_i (); + TAO_Connection_Handler * eh = this->invalidate_event_handler_i (); this->close_connection_shared (1, eh); } void TAO_Transport::close_connection_no_purge (void) { - ACE_Event_Handler * eh = this->invalidate_event_handler (); + TAO_Connection_Handler * eh = this->invalidate_event_handler (); this->close_connection_shared (0, eh); } - void TAO_Transport::close_connection_shared (int disable_purge, - ACE_Event_Handler * eh) + TAO_Connection_Handler * eh) { // Purge the entry if (!disable_purge) @@ -697,30 +692,13 @@ TAO_Transport::close_connection_shared (int disable_purge, return; } - int retval = 0; - - // We first try to remove the handler from the reactor. After that - // we destroy the handler using handle_close (). The remove handler - // is necessary because if the handle_closed is called directly, the - // reactor would be left with a dangling pointer. - if (this->ws_->is_registered ()) - { - retval = this->orb_core_->reactor ()->remove_handler ( - eh, - ACE_Event_Handler::ALL_EVENTS_MASK | - ACE_Event_Handler::DONT_CALL); - } - - // Yet another protocol using the Reactor. If a thread is not able - // to remove the handler from the Reactor, then he has no business - // to close down the handler. - if (retval == 0) - { - (void) eh->handle_close (ACE_INVALID_HANDLE, - ACE_Event_Handler::ALL_EVENTS_MASK); - } + eh->close_connection (); this->send_connection_closed_notifications (); + + // REFCNT: Matches incr_refcnt in XXX_Transport::XXX_Transport + // REFCNT: Only one of this or connection_handler_closing() run + eh->decr_refcount (); } int @@ -1062,13 +1040,13 @@ TAO_Transport::report_invalid_event_handler (const char *caller) if (TAO_debug_level > 0) { ACE_DEBUG ((LM_DEBUG, - "(%P|%t) - Transport[%d]::report_invalid_event_handler" + "TAO (%P|%t) - Transport[%d]::report_invalid_event_handler" "(%s) no longer associated with handler [tag=%d]\n", this->id (), caller, this->tag_)); } } -ACE_Event_Handler * +TAO_Connection_Handler * TAO_Transport::invalidate_event_handler (void) { ACE_MT (ACE_GUARD_RETURN (ACE_Lock, guard, *this->handler_lock_, 0)); @@ -1079,6 +1057,14 @@ TAO_Transport::invalidate_event_handler (void) void TAO_Transport::send_connection_closed_notifications (void) { + ACE_MT (ACE_GUARD (ACE_Lock, guard, *this->handler_lock_)); + + this->send_connection_closed_notifications_i (); +} + +void +TAO_Transport::send_connection_closed_notifications_i (void) +{ while (this->head_ != 0) { TAO_Queued_Message *i = this->head_; @@ -1160,6 +1146,14 @@ TAO_Transport::send_message_shared_i (TAO_Stub *stub, // server ... if (errno != EWOULDBLOCK && errno != ETIME) { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - Transport[%d]::send_message_i, " + "fatal error in " + "send_message_block_chain_i %p\n", + this->id (), "")); + } return -1; } } diff --git a/TAO/tao/Transport.h b/TAO/tao/Transport.h index b3a3426d3a0..1f0afb780ef 100644 --- a/TAO/tao/Transport.h +++ b/TAO/tao/Transport.h @@ -459,7 +459,7 @@ protected: * * @return The old event handler */ - virtual ACE_Event_Handler * invalidate_event_handler_i (void) = 0; + virtual TAO_Connection_Handler * invalidate_event_handler_i (void) = 0; /// Return the messaging object that is used to format the data that /// needs to be sent. @@ -845,7 +845,7 @@ private: /// not pending void reset_flush_timer (void); - + /// Print out error messages if the event handler is not valid void report_invalid_event_handler (const char *caller); @@ -863,12 +863,15 @@ private: int notify_reactor (void); /// Grab the mutex and then call invalidate_event_handler_i() - ACE_Event_Handler * invalidate_event_handler (void); + TAO_Connection_Handler * invalidate_event_handler (void); /// Notify all the components inside a Transport when the underlying /// connection is closed. void send_connection_closed_notifications (void); + /// Assume the lock is held + void send_connection_closed_notifications_i (void); + /// Implement close_connection() assuming the handler_lock_ is held. void close_connection_i (void); @@ -883,7 +886,7 @@ private: /// Close the underlying connection, implements the code shared by /// all the close_connection_* variants. void close_connection_shared (int disable_purge, - ACE_Event_Handler * eh); + TAO_Connection_Handler * eh); /// Prohibited ACE_UNIMPLEMENTED_FUNC (TAO_Transport (const TAO_Transport&)) |