From 5bf9e807bf91e9894da77eb55b01dafc2590d71f Mon Sep 17 00:00:00 2001 From: Ossama Othman Date: Wed, 8 Aug 2001 23:18:26 +0000 Subject: ChangeLogTag:Wed Aug 08 16:14:01 2001 Ossama Othman --- TAO/ChangeLogs/ChangeLog-02a | 63 ++++++++++++++++++++++ TAO/tao/DLL_ORB.cpp | 29 +++++----- TAO/tao/DLL_ORB.h | 26 ++++----- TAO/tao/TAO_Internal.cpp | 18 +++---- TAO/tao/TAO_Singleton_Manager.h | 91 ++++++++++++++++++-------------- TAO/tao/default_resource.cpp | 65 ++++++++++++++++++++--- TAO/tao/default_resource.h | 36 +++++++++++-- TAO/tests/DLL_ORB/Test_Client_Module.cpp | 15 ++++-- 8 files changed, 251 insertions(+), 92 deletions(-) diff --git a/TAO/ChangeLogs/ChangeLog-02a b/TAO/ChangeLogs/ChangeLog-02a index 795d020165c..5fee42ef92e 100644 --- a/TAO/ChangeLogs/ChangeLog-02a +++ b/TAO/ChangeLogs/ChangeLog-02a @@ -1,3 +1,66 @@ +Wed Aug 08 16:14:01 2001 Ossama Othman + + * tao/default_resource.h (TAO_Default_Resource_Factory): + + The default resource factory now also inherits from ACE_Cleanup + so that it may be registered for destruction with the + TAO_Singleton_Manager. This generally only necessary for the + default resource factory since it may be created during ORB + initialization, and it must exist long enough for the ORB + Core to make some calls on it during ORB Core finalization. + Resource factories that are statically or dynamically loaded + (i.e. registered with the Service Repository) before the ORB is + initialized need not inherit from ACE_Cleanup, nor is it + necessary for them to register with the TAO_Singleton_Manager. + + * tao/default_resource.cpp (_make_TAO_Default_Resource_Factory): + + A custom factory definition is used instead of the commonly used + one created by the ACE_FACTORY_DEFINE macro. This is necessary + to get around dynamic unloading issues. The default resource + factory must exist long enough for the ORB to make the a + resource factory reclaim the reactor, for example. The easiest + (and probably best) way to do that is register the + TAO_Default_Resource_Factory for destruction with the + TAO_Singleton_Manager. This fixes a segmentation fault (memory + access violation) that occurred when an ORB that was initialized + within a dynamically loaded object (e.g. within an + ACE_Service_Object instance) was finalized/destroyed. + + (ACE_STATIC_SVC_DEFINE): + + Do not set the ACE_Service_Type::DELETE_OBJ flag within the + TAO_Default_Resource_Factory-specific declaration/expansion of + this macro. The "payload" object, i.e. the default resource + factory, is now managed by the TAO_Singleton manager instead of + the Service Repository. + + * tao/DLL_ORB.h (TAO_DLL_ORB): + + Updated class documentation to mention the fact that this class + is deprecated, and why it should not be used. + + * tao/DLL_ORB.cpp (init): + + Added debugging message that mentions that the TAO_DLL_ORB class + is deprecated. + + * tao/TAO_Internal.cpp (open_i): + * tao/TAO_Singleton_Manager.h (TAO_Singleton_Manager): + + Updated and corrected class documentation. + + * tests/DLL_ORB/Test_Client_Module.cpp (fini): + + Explicitly release the reference to the target object. This is + a bit of a hack. The ORB Core's lifetime is tied to the + lifetime of an object reference. We need to wipe out all object + references before we call fini() on the TAO_Singleton_Manager. + This is a tough problem to correct. Fortunately, this is not a + problem when a resource factory is loaded into the Service + Repository before the ORB is initialized, i.e. when the default + resource factory is not used. + Wed Aug 8 15:03:58 2001 Balachandran Natarajan * tao/Strategies/DIOP_Transport.cpp (send_request): There was no diff --git a/TAO/tao/DLL_ORB.cpp b/TAO/tao/DLL_ORB.cpp index cf03d554124..31f9c8e80e1 100644 --- a/TAO/tao/DLL_ORB.cpp +++ b/TAO/tao/DLL_ORB.cpp @@ -6,7 +6,9 @@ #include "tao/TAO_Singleton_Manager.h" #include "tao/debug.h" -ACE_RCSID (tao, DLL_ORB, "$Id$") +ACE_RCSID (tao, + DLL_ORB, + "$Id$") #if !defined (__ACE_INLINE__) # include "tao/DLL_ORB.inl" @@ -26,6 +28,16 @@ TAO_DLL_ORB::~TAO_DLL_ORB (void) int TAO_DLL_ORB::init (int argc, ACE_TCHAR *argv[]) { + // This class is deprecated. See the class documentation in + // DLL_ORB.h for details explaining why this is so. + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_WARNING, + ACE_LIB_TEXT ("TAO (%P|%t) - The TAO_DLL_ORB class is ") + ACE_LIB_TEXT ("deprecated. See the class documentation\n") + ACE_LIB_TEXT ("TAO (%P|%t) - `tao/DLL_ORB.h' for details ") + ACE_LIB_TEXT ("explaining why this is so.\n"))); + + // Make sure TAO's singleton manager is initialized, and set to not // register itself with the ACE_Object_Manager since it is under the // control of the Service Configurator. @@ -39,23 +51,16 @@ TAO_DLL_ORB::init (int argc, ACE_TCHAR *argv[]) { ACE_ARGV new_argv; - // Respect the argc supplied by the user instead of the one - // calculated by the ACE_ARGV class. Also, add two to the new - // argc since "dummy -ORBSkipServiceConfigOpen" is being added - // to the argv vector. - int new_argc = argc + 2; - - // Prevent the ORB from opening the Service Configurator file - // again since the Service Configurator file is already in the - // process of being opened. - if (new_argv.add (ACE_TEXT ("dummy -ORBSkipServiceConfigOpen")) == -1 + if (new_argv.add (ACE_TEXT ("dummy")) == -1 || new_argv.add (argv) == -1) return -1; + int new_argc = new_argv.argc (); + // Initialize the ORB. this->orb_ = CORBA::ORB_init (new_argc, new_argv.argv (), - 0, + "", ACE_TRY_ENV); ACE_TRY_CHECK; diff --git a/TAO/tao/DLL_ORB.h b/TAO/tao/DLL_ORB.h index 10d5685caa5..74f1567f845 100644 --- a/TAO/tao/DLL_ORB.h +++ b/TAO/tao/DLL_ORB.h @@ -6,7 +6,7 @@ * * $Id$ * - * Header file for the TAO_DLL_ORB helper class. + * Header file for the TAO_DLL_ORB helper class. * * * @author Ossama Othman @@ -30,18 +30,20 @@ /** * @class TAO_DLL_ORB * - * @brief Manager for TAO library services and singleton cleanup. + * @brief Helper class that initializes an ORB when an instance of + * this class is dynamically loaded. * - * The is basically simplified version of - * the ACE_Object_Manager. It is designed specifically to - * manage singletons created by TAO. For example, Singleton - * instances created by TAO will be automatically registered - * with the Singleton instance of this Singleton Manager. - * This class is necessary to ensure that TAO-specific - * Singletons are centrally isolated. The idea is that - * destruction of the instance of the - * triggers destruction of all objects/services registered with - * it. + * This class is deprecated. While it does demonstrate how to + * initialize an ORB in a dynamically loaded object, the fact that it + * is located in the TAO library forces the TAO library to be linked + * to the application binary. This prevents TAO from being completely + * decoupled from an application when dynamic loading is used, hence + * defeating the purpose of dynamically loading the object! + * @par + * For an example of how to dynamically load an ORB (actually initialize + * an ORB inside a dynamically loaded object) that is completely + * decoupled from an application binary see the TAO/tests/DLL_ORB + * test. */ class TAO_Export TAO_DLL_ORB : public ACE_Task_Base { diff --git a/TAO/tao/TAO_Internal.cpp b/TAO/tao/TAO_Internal.cpp index 8b7f957361d..b65a7280a39 100644 --- a/TAO/tao/TAO_Internal.cpp +++ b/TAO/tao/TAO_Internal.cpp @@ -186,18 +186,12 @@ TAO_Internal::open_services_i (int &argc, if (TAO_Internal::service_open_count_++ == 0) { - // @@ We cannot insert the default resource factory into the - // Service Configurator before the ORB is created since it - // will be finalized before the ORB is finalized. The ORB - // requires that a resource factory exist in order to reclaim - // the reactor during finalization. Unfortunately, the - // resource factory must be inserted into the Service - // Repository so that Service Configurator directives such as - // 'static Resource_Factory "-ORBResources global"' actually - // work properly. - // - // This is only a problem when the ORB is dynamically - // loaded/unloaded. + // The ORB requires that a resource factory exist in order to + // reclaim the reactor during finalization. The default + // resource factory must be inserted into the Service Repository + // so that Service Configurator directives such as 'static + // Resource_Factory "-ORBResources global"' actually work + // properly. ACE_Service_Config::static_svcs ()-> insert (&ace_svc_desc_TAO_Default_Resource_Factory); ACE_Service_Config::static_svcs ()-> diff --git a/TAO/tao/TAO_Singleton_Manager.h b/TAO/tao/TAO_Singleton_Manager.h index 20352e50ba9..3cb90214779 100644 --- a/TAO/tao/TAO_Singleton_Manager.h +++ b/TAO/tao/TAO_Singleton_Manager.h @@ -10,7 +10,6 @@ * Header file for the TAO-specific Singleton Manager. Based * entirely on ace/Object_Manager.{h,i,cpp}. * - * * @author Ossama Othman */ //============================================================================= @@ -41,16 +40,17 @@ TAO_Singleton_Manager_cleanup_destroyer (void *, void *); * * @brief Manager for TAO library services and singleton cleanup. * - * The is basically simplified version of - * the ACE_Object_Manager. It is designed specifically to - * manage singletons created by TAO. For example, Singleton - * instances created by TAO will be automatically registered - * with the Singleton instance of this Singleton Manager. + * The TAO_Singleton_Manager is basically simplified version of the + * ACE_Object_Manager. It is designed specifically to manage + * singletons created by TAO. For example, singleton instances + * created by TAO will be automatically registered with the singleton + * instance of this Singleton Manager. + * @par * This class is necessary to ensure that TAO-specific - * Singletons are centrally isolated. The idea is that - * destruction of the instance of the - * triggers destruction of all objects/services registered with - * it. + * singletons are isolated to TAO itself, not ACE, for example. The + * idea is that destruction of the instance of the + * TAO_Singleton_Manager triggers destruction of all objects/services + * registered with it. */ class TAO_Export TAO_Singleton_Manager : public ACE_Object_Manager_Base { @@ -58,6 +58,7 @@ class TAO_Export TAO_Singleton_Manager : public ACE_Object_Manager_Base friend void TAO_Singleton_Manager_cleanup_destroyer (void *, void *); public: + /// Explicitly initialize. virtual int init (void); @@ -72,66 +73,69 @@ public: virtual int fini (void); /** - * Returns 1 before the has been - * constructed. See for more - * information. + * Returns 1 before the TAO_Singleton_Manager has been constructed. + * See ACE_Object_Manager::starting_up for more information. */ static int starting_up (void); - /// Returns 1 after the has been destroyed. - /// See for more information. + /// Returns 1 after the TAO_Singleton_Manager has been destroyed. + /// See ACE_Object_Manager::shutting_down for more information. static int shutting_down (void); + /// Unique identifiers for preallocated Objects. enum Preallocated_Object { # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) - // @@ No MT-specific preallocated objects (yet). Remove the - // below dummy enum once a preallocated object is added. + /// @@ No MT-specific preallocated objects (yet). Remove the + /// below dummy enum once a preallocated object is added. TAO_EMPTY_PREALLOCATED_OBJECT, # else - // Without ACE_MT_SAFE, There are no preallocated objects. Make - // sure that the preallocated_array size is at least one by - // declaring this dummy . . . + /// Without ACE_MT_SAFE, There are no preallocated objects. + /// Make sure that the preallocated_array size is at least one + /// by declaring this dummy ... TAO_EMPTY_PREALLOCATED_OBJECT, # endif /* ACE_MT_SAFE */ - TAO_PREALLOCATED_OBJECTS // This enum value must be last! + /// This enum value must be last! + TAO_PREALLOCATED_OBJECTS }; - // Unique identifiers for preallocated objects. + /// Accesses a default signal set used, for example, in - /// methods. + /// ACE_Sig_Guard methods. static sigset_t *default_mask (void); /// Returns the current thread hook for the process. static ACE_Thread_Hook *thread_hook (void); - /// Returns the existing thread hook and assign a . + /// Returns the existing thread hook and assign a new_thread_hook. static ACE_Thread_Hook *thread_hook (ACE_Thread_Hook *new_thread_hook); /// Accessor to singleton instance. static TAO_Singleton_Manager *instance (void); + /// Register an ACE_Cleanup object for cleanup at process + /// termination. /** - * Register an ACE_Cleanup object for cleanup at process - * termination. The object is deleted via the - * . If you need more flexiblity, see the - * method below. For OS's that do not have - * processes, cleanup takes place at the end of
. Returns 0 - * on success. On failure, returns -1 and sets errno to: EAGAIN if - * shutting down, ENOMEM if insufficient virtual memory, or EEXIST - * if the object (or array) had already been registered. + * The object is deleted via the ace_cleanup_destroyer. If you need + * more flexiblity, see the other at_exit method below. For OS's + * that do not have processes, cleanup takes place at the end of + * main. Returns 0 on success. On failure, returns -1 and sets + * errno to: EAGAIN if shutting down, ENOMEM if insufficient virtual + * memory, or EEXIST if the object (or array) had already been + * registered. */ static int at_exit (ACE_Cleanup *object, void *param = 0); + /// Register an object (or array) for cleanup at process + /// termination. /** - * Register an object (or array) for cleanup at process termination. - * "cleanup_hook" points to a (global, or static member) function - * that is called for the object or array when it to be destroyed. - * It may perform any necessary cleanup specific for that object or - * its class. "param" is passed as the second parameter to the - * "cleanup_hook" function; the first parameter is the object (or - * array) to be destroyed. "cleanup_hook", for example, may delete + * cleanup_hook points to a (global, or static member) function that + * is called for the object or array when it to be destroyed. It + * may perform any necessary cleanup specific for that object or its + * class. param is passed as the second parameter to the + * cleanup_hook function; the first parameter is the object (or + * array) to be destroyed. cleanup_hook, for example, may delete * the object (or array). For OS's that do not have processes, this * function is the same as . Returns 0 on success. * On failure, returns -1 and sets errno to: EAGAIN if shutting @@ -143,13 +147,18 @@ public: void *param); private: - // Force allocation on the heap. + + /// Force allocation on the heap. + //@{ TAO_Singleton_Manager (void); ~TAO_Singleton_Manager (void); + //@} - // Disallow copying by not implementing the following . . . + /// Disallow copying by not implementing the following ... + //@{ TAO_Singleton_Manager (const TAO_Singleton_Manager &); TAO_Singleton_Manager &operator= (const TAO_Singleton_Manager &); + //@} /// Register an object or array for deletion at program termination. /// See description of static version above for return values. diff --git a/TAO/tao/default_resource.cpp b/TAO/tao/default_resource.cpp index 43b8db95560..a322fd2f718 100644 --- a/TAO/tao/default_resource.cpp +++ b/TAO/tao/default_resource.cpp @@ -28,7 +28,9 @@ # include "tao/default_resource.i" #endif /* ! __ACE_INLINE__ */ -ACE_RCSID(tao, default_resource, "$Id$") +ACE_RCSID (tao, + default_resource, + "$Id$") TAO_Default_Resource_Factory::TAO_Default_Resource_Factory (void) : use_tss_resources_ (0), @@ -65,11 +67,11 @@ TAO_Default_Resource_Factory::~TAO_Default_Resource_Factory (void) ++i) CORBA::string_free (this->parser_names_[i]); - delete []this->parser_names_; + delete [] this->parser_names_; } int -TAO_Default_Resource_Factory::init (int argc, char **argv) +TAO_Default_Resource_Factory::init (int argc, char *argv[]) { ACE_TRACE ("TAO_Default_Resource_Factory::init"); @@ -100,8 +102,9 @@ TAO_Default_Resource_Factory::init (int argc, char **argv) if (curarg == (argc-1) && this->parser_names_count_ != 0) { // This is the last loop.. - this->parser_names_ = - new char *[this->parser_names_count_]; + ACE_NEW_RETURN (this->parser_names_, + char *[this->parser_names_count_], + -1); for (int i = 0; i < this->parser_names_count_; @@ -919,13 +922,61 @@ TAO_Default_Resource_Factory::disable_factory (void) // **************************************************************** +// Notice that the Service Configurator/Repository will not deallocate +// the *payload* object, i.e. the default resource factory. The +// TAO_Singleton_Manager will deallocate it. This is necessary since +// the ORB Core requires that a resource factory exist as it is being +// finalized. Resource factories that are statically or dynamically +// loaded (i.e. registered with the Service Repository) should +// generally enable the ACE_Service_Type::DELETE_OBJ service +// descriptor flag. ACE_STATIC_SVC_DEFINE (TAO_Default_Resource_Factory, ACE_TEXT ("Resource_Factory"), ACE_SVC_OBJ_T, &ACE_SVC_NAME (TAO_Default_Resource_Factory), - ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, + ACE_Service_Type::DELETE_THIS + /* | ACE_Service_Type::DELETE_OBJ */ /* SEE ABOVE */, 0) -ACE_FACTORY_DEFINE (TAO, TAO_Default_Resource_Factory) + +// @@ See below for an explanation of why this macro is not used for +// the TAO_Default_Resource_Factory. +// ACE_FACTORY_DEFINE (TAO, TAO_Default_Resource_Factory) + + +// A custom factory definition is used instead of the commonly used +// one created by the ACE_FACTORY_DEFINE macro below. This is +// necessary to get around dynamic unloading issues. The default +// resource factory must exist long enough for the ORB to make the +// resource factory reclaim the reactor, for example. The easiest +// (and probably best) way to do that is register the +// TAO_Default_Resource_Factory for destruction with the +// TAO_Singleton_Manager. +extern "C" ACE_Service_Object * +_make_TAO_Default_Resource_Factory (ACE_Service_Object_Exterminator *gobbler) +{ + // The TAO_Singleton_Manager will "gobble" the payload + // (TAO_Default_Resource_Factory) object. Set the gobbler function + // invoked by the Service_Type implementation to be to be nil. + *gobbler = 0; + + TAO_Default_Resource_Factory *rf = 0; + ACE_NEW_RETURN (rf, + TAO_Default_Resource_Factory, + 0); + + // Register for destruction with the TAO_Singleton_Manager. + // + // Note that the instance of the TAO_Default_Resource_Factory just + // created is not a Singleton. The TAO_Singleton_Manager is useful + // for more than just Singleton managment. + if (TAO_Singleton_Manager::at_exit (rf) != 0) + { + delete rf; + return 0; + } + + return rf; +} // **************************************************************** diff --git a/TAO/tao/default_resource.h b/TAO/tao/default_resource.h index 917a5f7eb14..f9a00aceb11 100644 --- a/TAO/tao/default_resource.h +++ b/TAO/tao/default_resource.h @@ -37,25 +37,47 @@ class TAO_LF_Strategy; * factory can return resource instances which are, e.g., global, * stored in thread-specific storage, stored in shared memory, * etc. + * + * @note The default resource factory also inherits from ACE_Cleanup + * so that it may be registered for destruction with the + * TAO_Singleton_Manager. This generally only necessary for + * default resource factory since it may be created during ORB + * initialization, and it must exist long enough for the ORB + * Core to make some calls on it during ORB Core finalization. + * Resource factories that are statically or dynamically loaded + * (i.e. registered with the Service Repository) before the ORB + * is initialized need not inherit from ACE_Cleanup, nor is it + * necessary for them to register with the + * TAO_Singleton_Manager. */ -class TAO_Export TAO_Default_Resource_Factory : public TAO_Resource_Factory +class TAO_Export TAO_Default_Resource_Factory + : public TAO_Resource_Factory, + public ACE_Cleanup { public: - // = Initialization and termination methods. + /// Constructor. TAO_Default_Resource_Factory (void); /// Destructor. virtual ~TAO_Default_Resource_Factory (void); - // = Service Configurator hooks. + /** + * @name Service Configurator Hooks + */ + //@{ /// Dynamic linking hook - virtual int init (int argc, char* argv[]); + virtual int init (int argc, char *argv[]); /// Parse svc.conf arguments int parse_args (int argc, char* argv[]); + //@} + + /** + * @name Member Accessors + */ + //@{ - /// = Member Accessors int get_parser_names (char **&names, int &number_of_names); enum @@ -102,7 +124,10 @@ public: virtual void disable_factory (void); + //@} + protected: + /// Obtain the reactor implementation virtual ACE_Reactor_Impl *allocate_reactor_impl (void) const; @@ -113,6 +138,7 @@ protected: const char* option_value); protected: + /// Flag indicating whether resources should be global or /// thread-specific. int use_tss_resources_; diff --git a/TAO/tests/DLL_ORB/Test_Client_Module.cpp b/TAO/tests/DLL_ORB/Test_Client_Module.cpp index 515ebf62be2..c9b82722ea8 100644 --- a/TAO/tests/DLL_ORB/Test_Client_Module.cpp +++ b/TAO/tests/DLL_ORB/Test_Client_Module.cpp @@ -108,7 +108,7 @@ Test_Client_Module::init (int argc, ACE_TCHAR *argv[]) if (CORBA::is_nil (this->test_.in ())) { ACE_ERROR_RETURN ((LM_DEBUG, - "Nil Test reference <%s>\n", + ACE_TEXT ("Nil Test reference <%s>\n"), ior), 1); } @@ -158,11 +158,20 @@ Test_Client_Module::fini (void) ACE_ENDTRY; ACE_CHECK_RETURN (-1); + // This is a bit of a hack. The ORB Core's lifetime is tied to the + // lifetime of an object reference. We need to wipe out all object + // references before we call fini() on the TAO_Singleton_Manager. + // + // Note that this is only necessary if the default resource factory + // is used, i.e. one isn't explicitly loaded prior to initializing + // the ORB. + (void) this->test_.out (); + // ------------------------------------------------------------ // Pre-Test_Client_Module termination steps. // ------------------------------------------------------------ - // Explicitly clean up singletons created by TAO before - // unloading this module. + // Explicitly clean up singletons and other objects created by TAO + // before unloading this module. if (TAO_Singleton_Manager::instance ()->fini () == -1) ACE_ERROR_RETURN ((LM_ERROR, "Test_Client_Module::fini -- ORB pre-termination " -- cgit v1.2.1