Bug 4062 - Notification Service: crash during deactivation
Summary: Notification Service: crash during deactivation
Status: NEW
Alias: None
Product: TAO
Classification: Unclassified
Component: Notification Service (show other bugs)
Version: 2.0.5
Hardware: All other
: P3 minor
Assignee: DOC Center Support List (internal)
URL:
Depends on:
Blocks:
 
Reported: 2012-07-24 07:30 CDT by Dmitry Medvedev
Modified: 2012-08-06 03:53 CDT (History)
1 user (show)

See Also:


Attachments
test example, that reproduced this bug (3.46 KB, text/plain)
2012-07-24 07:30 CDT, Dmitry Medvedev
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Dmitry Medvedev 2012-07-24 07:30:04 CDT
Created attachment 1423 [details]
test example, that reproduced this bug

PROBLEM-REPORT-FORM:
    TAO VERSION: 2.0.5
    ACE VERSION: 6.0.5

    HOST MACHINE and OPERATING SYSTEM:
        Windows 7 x64
        Windows Socket 2.0 32 bit - 6.1.7600.16385

    COMPILER NAME AND VERSION (AND PATCHLEVEL): Visual Studio 2009 SP1: 9.0.30729.1

    THE $ACE_ROOT/ace/config.h FILE:
        #define ACE_HAS_STANDARD_CPP_LIBRARY 1
        #include "ace/config-win32.h"

    THE $ACE_ROOT/include/makeinclude/platform_macros.GNU FILE:
        none

    CONTENTS OF $ACE_ROOT/bin/MakeProjectCreator/config/default.features
    (used by MPC when you generate your own makefiles):
        none

    AREA/CLASS/EXAMPLE AFFECTED:
        In attach

    DOES THE PROBLEM AFFECT:
        COMPILATION?
            no
        LINKING?
            no
        EXECUTION?
            yes
        OTHER (please specify)?
            crash

    SYNOPSIS:
        An application with integrated notification service (TAO_Notify_Service) crashes with error "access violation" during POA deactivation.
        Cause: premature deletion of POA, in which EventChannelFactory is activated.

    DESCRIPTION:

        Error is reproduced by the next steps (test example is in attachment):

        Initialization:
        1. Init and start ORB
        2. Integrate notification service into application using TAO_Notify_Service::load_default ()
        3. Create the Event Channel Factory

        Stopping:
        (do not call NotifyExt::EventChannelFactory::destroy, because it is not specified by CORBA standard )
        4. Unload notification service using finalize_service() and fini()
        5. Explicitly deactivate POA Manager using deactivate( true, true )

        Crash:
        6. During POA Manager deactivation the application crashes with error "access violation", due to access attempt to destroyed POA.

        Description of crash dump.

        Crash dump stack:
                 TAO_PortableServerd.dll!TAO::Portable_Server::Active_Policy_Strategies::servant_retention_strategy()  Line 57 + 0x3 bytes        C++
                 TAO_PortableServerd.dll!TAO_Root_POA::unbind_using_user_id(const CORBA::OctetSeq & user_id={...})  Line 1484 + 0xe bytes        C++
        >        TAO_PortableServerd.dll!TAO::Portable_Server::RequestProcessingStrategyAOMOnly::cleanup_servant(TAO_ServantBase * servant=0x023d6f18, const CORBA::OctetSeq & user_id={...})  Line 121 + 0xf bytes        C++
                 TAO_PortableServerd.dll!TAO_Root_POA::cleanup_servant(TAO_ServantBase * servant=0x023d6f18, const CORBA::OctetSeq & user_id={...})  Line 1493 + 0x28 bytes        C++
                 TAO_PortableServerd.dll!TAO::Portable_Server::ServantRetentionStrategyRetain::deactivate_map_entry(TAO_Active_Object_Map_Entry * active_object_map_entry=0x023d7878)  Line 111        C++
                 TAO_PortableServerd.dll!TAO::Portable_Server::ServantRetentionStrategyRetain::deactivate_all_objects()  Line 485        C++
                 TAO_PortableServerd.dll!TAO_Root_POA::deactivate_all_objects_i(bool etherealize_objects=true)  Line 1257 + 0x23 bytes        C++
                 TAO_PortableServerd.dll!TAO_Root_POA::deactivate_all_objects_i(bool etherealize_objects=true, bool wait_for_completion=true)  Line 1194        C++
                 TAO_PortableServerd.dll!TAO_POA_Manager::deactivate_i(bool etherealize_objects=true, bool wait_for_completion=true)  Line 145        C++
                 TAO_PortableServerd.dll!TAO_POA_Manager::deactivate(bool etherealize_objects=true, bool wait_for_completion=true)  Line 53        C++

        Error occurs in method RequestProcessingStrategyAOMOnly::cleanup_servant:
            void
            RequestProcessingStrategyAOMOnly::cleanup_servant (
              PortableServer::Servant servant,
              const PortableServer::ObjectId &user_id)
            {
              if (servant)
                {
                  // ATTENTION: Trick locking here, see class header for details
                  Non_Servant_Upcall non_servant_upcall (*this->poa_);
                  ACE_UNUSED_ARG (non_servant_upcall);

                  try
                    {
                      servant->_remove_ref ();
                    }
                  catch (...)
                    {
                      // Ignore exceptions from servant cleanup.
                    }
                }

              // This operation causes the association of the Object Id specified
              // by the oid parameter and its servant to be removed from the
              // Active Object Map.
              if (this->poa_->unbind_using_user_id (user_id) != 0)
                {
                  throw ::CORBA::OBJ_ADAPTER ();
                }
            }

        Call of servant->_remove_ref (); destroys Event Channel Factory servant. Destructor of Event Channel Factory destroys poa_, it leads to access violation in
                if (this->poa_->unbind_using_user_id (user_id) != 0)

    REPEAT BY:
        in attachment

    SAMPLE FIX/WORKAROUND:
        FIX.
          Examine whether it is right that destructor of servant destroys POA. In this case it is the destructor of the base class of Event Channel Factory:
TAO_Notify_Object::~TAO_Notify_Object ()
{
  if (TAO_debug_level > 2 )
    ACE_DEBUG ((LM_DEBUG,"object:%x  destroyed\n", this ));

  this->destroy_proxy_poa ();
  this->destroy_object_poa ();
  this->destroy_poa ();
}          
          If it is not right, then it is necessary to revise the interaction of TAO_Notify_Service with POA.

        WORKAROUND. Before POA deactivation explicitly destroy Event Channel Factory using TAO-specific interface:
          NotifyExt::EventChannelFactory_var eventChannelFactoryExt = NotifyExt::EventChannelFactory::_narrow( eventChannelFactory_ );
          eventChannelFactoryExt->destroy();
Comment 1 Johnny Willemsen 2012-07-24 07:36:30 CDT
Proposal to extend destructor of servant to destroy POA is not a good solution. 
Comment 2 Dmitry Medvedev 2012-07-24 09:41:12 CDT
I would like to clarify:
  The code from SAMPLE FIX is a copy of the current TAO's code.
  That is, in the current version of TAO Notification Service the POA is destroyed by servant destructor.

I agree - it's not a good solution. Furthermore, the methods destroy_proxy_poa, destroy_proxy_poa, destroy_poa are not specified by CORBA specification.

My proposal: refine code and eliminate this methods.

Are there any ideas, why this code (destroying POA in servant destructor) has been added? I do not understand this yet.

Thanks.