summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Huston <shuston@riverace.com>2010-04-20 19:01:24 +0000
committerSteve Huston <shuston@riverace.com>2010-04-20 19:01:24 +0000
commit369c0bf707c1520baf496fb4c8c467f7c4a03374 (patch)
tree01471c1a8794c7e1aecd1380c4a1e32bd1e56964
parent89e1b5e60ea84c3caebbbf8d106689f0e375655c (diff)
downloadATCD-369c0bf707c1520baf496fb4c8c467f7c4a03374.tar.gz
Tue Apr 20 18:46:38 UTC 2010 Steve Huston <shuston@riverace.com>
* tests/Service_Config_Stream_Test.{cp conf}: Brought this test over from hte dev stream as well as Bug_3334_Regression_Test.cpp. Mon Apr 19 18:17:30 UTC 2010 UTC 2010 Chad Beaulac <chad@objectivesolutions.com> * ace/Service_Repository.cpp Modified ASR::fini to print debug info for empty service entries and handle empty service entries. This fixes the ASR remove functionality that was one of the reasons SC_Server was crashing at shutdown. * examples/ASX/CCM_App/SC_Server.cpp Removing signal handler before main exit to present SEGV This fixes Bugzilla #2916 and #3205. Mon Apr 19 12:44:56 UTC 2010 Chad Beaulac <chad@objectivesolutions.com> * ace/Service_Types.h * ace/Service_Types.inl * ace/Service_Types.cpp Added service_type_ attr to expose the type of service being managed to the ACE_Service_Repository. This allows the ASR to manage the lifecycle of the ACE_Module and ACE_Stream in order to avoid a double delete of ACE_Module at shutdown. ACE_Stream_Type::fini was modified to not call ACE_Module_Type::fini as this will results in a double delete when ACE_Service_Repository::fini is called. ACE_Stream_Type::remove(module_name) was modified to not call ACE_Module_Type::fini as this will results in a double delete when ACE_Service_Repository::fini is called also. * ace/Service_Repository.cpp Modified ASR::fini to iterate over the service_array_ twice. ACE_Service_Type::fini is called on all ACE_Stream_Type and ACE_Service_Object_Type instances first. Then, fini is called on all ACE_Modules_Type instances. All calls to fini are done in the order the services appear in the ASR::service_array_ except for the grouping described here. The calls to ACE_Module_Type::fini must be done last because ACE_Stream_Type::fini accesses the Modules so they must not be deleted by a call to ACE_Module_Type::fini before that. * tests/Bug_3334_Regresssion_Test.cpp Added call to ACE_Service_Repository::fini_svcs() to capture all debug output before the application exits. * tests/run_tests.lst Removed !FIXED_BUGS_ONLY from Bug_3334_Regression_Test This fixes Bugzilla #3334
-rw-r--r--ChangeLog55
-rw-r--r--ace/Service_Repository.cpp90
-rw-r--r--ace/Service_Types.cpp39
-rw-r--r--ace/Service_Types.h23
-rw-r--r--ace/Service_Types.inl11
-rw-r--r--examples/ASX/CCM_App/SC_Server.cpp1
-rw-r--r--tests/Bug_3334_Regression_Test.conf7
-rw-r--r--tests/Bug_3334_Regression_Test.cpp48
-rw-r--r--tests/Service_Config_Stream_DLL.h44
-rw-r--r--tests/Service_Config_Stream_DLL_Export.h38
-rw-r--r--tests/Service_Config_Stream_Test.conf25
-rw-r--r--tests/Service_Config_Stream_Test.cpp131
-rw-r--r--tests/run_test.lst1
-rw-r--r--tests/tests.mpc32
14 files changed, 499 insertions, 46 deletions
diff --git a/ChangeLog b/ChangeLog
index 7dc732d1b3b..72a8596b079 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+Tue Apr 20 18:46:38 UTC 2010 Steve Huston <shuston@riverace.com>
+
+ * tests/Service_Config_Stream_Test.{cp conf}: Brought this test over
+ from hte dev stream as well as Bug_3334_Regression_Test.cpp.
+
+Mon Apr 19 18:17:30 UTC 2010 UTC 2010 Chad Beaulac <chad@objectivesolutions.com>
+
+ * ace/Service_Repository.cpp
+ Modified ASR::fini to print debug info for empty
+ service entries and handle empty service entries.
+ This fixes the ASR remove functionality that was
+ one of the reasons SC_Server was crashing at shutdown.
+
+ * examples/ASX/CCM_App/SC_Server.cpp
+ Removing signal handler before main exit to present SEGV
+
+ This fixes Bugzilla #2916 and #3205.
+
+Mon Apr 19 12:44:56 UTC 2010 Chad Beaulac <chad@objectivesolutions.com>
+
+ * ace/Service_Types.h
+ * ace/Service_Types.inl
+ * ace/Service_Types.cpp
+ Added service_type_ attr to expose the type of service being
+ managed to the ACE_Service_Repository. This allows the ASR to
+ manage the lifecycle of the ACE_Module and ACE_Stream in order to
+ avoid a double delete of ACE_Module at shutdown.
+
+ ACE_Stream_Type::fini was modified to not call ACE_Module_Type::fini
+ as this will results in a double delete when
+ ACE_Service_Repository::fini is called.
+ ACE_Stream_Type::remove(module_name) was modified to not call
+ ACE_Module_Type::fini as this will results in a double delete
+ when ACE_Service_Repository::fini is called also.
+
+ * ace/Service_Repository.cpp
+ Modified ASR::fini to iterate over the service_array_ twice.
+ ACE_Service_Type::fini is called on all ACE_Stream_Type and
+ ACE_Service_Object_Type instances first. Then, fini is called on
+ all ACE_Modules_Type instances. All calls to fini are done in the
+ order the services appear in the ASR::service_array_ except for
+ the grouping described here. The calls to ACE_Module_Type::fini
+ must be done last because ACE_Stream_Type::fini accesses the Modules
+ so they must not be deleted by a call to ACE_Module_Type::fini
+ before that.
+
+ * tests/Bug_3334_Regresssion_Test.cpp
+ Added call to ACE_Service_Repository::fini_svcs() to capture all
+ debug output before the application exits.
+
+ * tests/run_tests.lst
+ Removed !FIXED_BUGS_ONLY from Bug_3334_Regression_Test
+
+ This fixes Bugzilla #3334
+
Tue Apr 13 19:34:40 UTC 2010 Steve Huston <shuston@riverace.com>
* ace/Dev_Poll_Reactor.{h cpp}: Reorder the enqueue/pipe operations
diff --git a/ace/Service_Repository.cpp b/ace/Service_Repository.cpp
index 60f6b6fe831..d997c5e61cc 100644
--- a/ace/Service_Repository.cpp
+++ b/ace/Service_Repository.cpp
@@ -113,7 +113,9 @@ ACE_Service_Repository::ACE_Service_Repository (size_t size)
ACE_TRACE ("ACE_Service_Repository::ACE_Service_Repository");
}
+
/// Finalize (call fini() and possibly delete) all the services.
+
int
ACE_Service_Repository::fini (void)
{
@@ -121,45 +123,89 @@ ACE_Service_Repository::fini (void)
ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
int retval = 0;
-
// Do not be tempted to use the prefix decrement operator. Use
// postfix decrement operator since the index is unsigned and may
// wrap around the 0
- for (size_t i = this->service_array_.size(); i-- != 0; )
+ //
+ // debug output for empty service entries
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ {
+ for (size_t i = this->service_array_.size (); i-- != 0;)
{
- // <fini> the services in reverse order.
ACE_Service_Type *s =
const_cast<ACE_Service_Type *> (this->service_array_[i]);
+ if (s == 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SR::fini, repo=%@ [%d] -> 0\n"),
+ this,
+ i));
+ }
+ }
+#endif
+ //
+ // Remove all the Service_Object and Stream instances
+ //
+ for (size_t i = this->service_array_.size (); i-- != 0;)
+ {
+ // <fini> the services in reverse order.
+ ACE_Service_Type *s =
+ const_cast<ACE_Service_Type *> (this->service_array_[i]);
+ if (s != 0 && (s->type ()->service_type () != ACE_Service_Type::MODULE))
+ {
#ifndef ACE_NLOGGING
if (ACE::debug ())
- {
- if (s != 0)
- ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT ("ACE (%P|%t) SR::fini, repo=%@ [%d], ")
- ACE_TEXT ("name=%s, type=%@, object=%@, active=%d\n"),
- this,
- i,
- s->name(),
- s->type (),
- (s->type () != 0) ? s->type ()->object () : 0,
- s->active ()));
- else
- ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT ("ACE (%P|%t) SR::fini, repo=%@ [%d] -> 0\n"),
- this,
- i));
- }
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SR::fini, repo=%@ [%d], ")
+ ACE_TEXT ("name=%s, type=%@, object=%@, active=%d\n"),
+ this,
+ i,
+ s->name (),
+ s->type (),
+ (s->type () != 0) ? s->type ()->object () : 0,
+ s->active ()));
+ }
#endif
// Collect any errors.
- if (s != 0)
- retval += s->fini ();
+ retval += s->fini ();
}
+ }
+ //
+ // Remove all the Module instances
+ //
+ for (size_t i = this->service_array_.size (); i-- != 0;)
+ {
+ // <fini> the services in reverse order.
+ ACE_Service_Type *s =
+ const_cast<ACE_Service_Type *> (this->service_array_[i]);
+ if (s != 0 && (s->type ()->service_type () == ACE_Service_Type::MODULE))
+ {
+#ifndef ACE_NLOGGING
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ACE (%P|%t) SR::fini, repo=%@ [%d], ")
+ ACE_TEXT ("name=%s, type=%@, object=%@, active=%d\n"),
+ this,
+ i,
+ s->name (),
+ s->type (),
+ (s->type () != 0) ? s->type ()->object () : 0,
+ s->active ()));
+ }
+#endif
+ // Collect any errors.
+ retval += s->fini ();
+ }
+ }
return (retval == 0) ? 0 : -1;
}
+
/// Close down all the services.
int
ACE_Service_Repository::close (void)
diff --git a/ace/Service_Types.cpp b/ace/Service_Types.cpp
index 4552607640e..5c2c2fae3b7 100644
--- a/ace/Service_Types.cpp
+++ b/ace/Service_Types.cpp
@@ -35,11 +35,13 @@ ACE_Service_Type_Impl::dump (void) const
ACE_Service_Type_Impl::ACE_Service_Type_Impl (void *so,
const ACE_TCHAR *s_name,
u_int f,
- ACE_Service_Object_Exterminator gobbler)
+ ACE_Service_Object_Exterminator gobbler,
+ int stype)
: name_ (0),
obj_ (so),
gobbler_ (gobbler),
- flags_ (f)
+ flags_ (f),
+ service_type_ (stype)
{
ACE_TRACE ("ACE_Service_Type_Impl::ACE_Service_Type_Impl");
this->name (s_name);
@@ -82,8 +84,9 @@ ACE_Service_Type_Impl::fini (void) const
ACE_Service_Object_Type::ACE_Service_Object_Type (void *so,
const ACE_TCHAR *s_name,
u_int f,
- ACE_Service_Object_Exterminator gobbler)
- : ACE_Service_Type_Impl (so, s_name, f, gobbler)
+ ACE_Service_Object_Exterminator gobbler,
+ int stype)
+ : ACE_Service_Type_Impl (so, s_name, f, gobbler, stype)
, initialized_ (-1)
{
ACE_TRACE ("ACE_Service_Object_Type::ACE_Service_Object_Type");
@@ -164,8 +167,9 @@ ACE_Module_Type::dump (void) const
ACE_Module_Type::ACE_Module_Type (void *m,
const ACE_TCHAR *m_name,
- u_int f)
- : ACE_Service_Type_Impl (m, m_name, f)
+ u_int f,
+ int stype)
+ : ACE_Service_Type_Impl (m, m_name, f, 0, stype)
{
ACE_TRACE ("ACE_Module_Type::ACE_Module_Type");
}
@@ -230,7 +234,6 @@ int
ACE_Module_Type::fini (void) const
{
ACE_TRACE ("ACE_Module_Type::fini");
-
void *obj = this->object ();
MT_Module *mod = (MT_Module *) obj;
MT_Task *reader = mod->reader ();
@@ -324,8 +327,9 @@ ACE_Stream_Type::resume (void) const
ACE_Stream_Type::ACE_Stream_Type (void *s,
const ACE_TCHAR *s_name,
- u_int f)
- : ACE_Service_Type_Impl (s, s_name, f),
+ u_int f,
+ int stype)
+ : ACE_Service_Type_Impl (s, s_name, f, 0, stype),
head_ (0)
{
ACE_TRACE ("ACE_Stream_Type::ACE_Stream_Type");
@@ -361,17 +365,13 @@ ACE_Stream_Type::fini (void) const
void *obj = this->object ();
MT_Stream *str = (MT_Stream *) obj;
- for (ACE_Module_Type *m = this->head_; m != 0; )
- {
- ACE_Module_Type *t = m->link ();
+ for (ACE_Module_Type *m = this->head_; m != 0;)
+ {
+ ACE_Module_Type *t = m->link ();
// Final arg is an indication to *not* delete the Module.
str->remove (m->name (),
- MT_Module::M_DELETE_NONE);
-
- // Finalize the Module (this may delete it, but we don't really
- // care since we don't access it again).
- m->fini ();
+ MT_Module::M_DELETE_NONE);
m = t;
}
str->close ();
@@ -408,9 +408,8 @@ ACE_Stream_Type::remove (ACE_Module_Type *mod)
MT_Module::M_DELETE_NONE) == -1)
result = -1;
- // This call may end up deleting m, which is ok since we
- // don't access it again!
- m->fini ();
+ // Do not call m->fini (); as this will result in a double delete
+ // of the ACE_Module_type when ACE_Service_Repository::fini is called
}
else
prev = m;
diff --git a/ace/Service_Types.h b/ace/Service_Types.h
index e741561d965..de442a6b431 100644
--- a/ace/Service_Types.h
+++ b/ace/Service_Types.h
@@ -43,7 +43,8 @@ public:
ACE_Service_Type_Impl (void *object,
const ACE_TCHAR *s_name,
u_int flags = 0,
- ACE_Service_Object_Exterminator gobbler = 0);
+ ACE_Service_Object_Exterminator gobbler = 0,
+ int stype = ACE_Service_Type::INVALID_TYPE);
virtual ~ACE_Service_Type_Impl (void);
// = Pure virtual interface (must be defined by the subclass).
@@ -65,6 +66,12 @@ public:
/// Dump the state of an object.
void dump (void) const;
+ /// get the service_type of this service
+ int service_type (void) const;
+
+ /// set the service_type of this service
+ void service_type (int stype);
+
/// Declare the dynamic allocation hooks.
ACE_ALLOC_HOOK_DECLARE;
@@ -81,6 +88,11 @@ protected:
/// Flags that control serivce behavior (particularly deletion).
u_int flags_;
+
+ /// type of this service
+ /// Used to properly manage the lifecycle of ACE_Modules and ACE_Streams
+ /// during shutdown
+ int service_type_;
};
/**
@@ -96,7 +108,8 @@ public:
ACE_Service_Object_Type (void *so,
const ACE_TCHAR *name,
u_int flags = 0,
- ACE_Service_Object_Exterminator gobbler = 0);
+ ACE_Service_Object_Exterminator gobbler = 0,
+ int stype = ACE_Service_Type::SERVICE_OBJECT);
~ACE_Service_Object_Type (void);
@@ -124,7 +137,8 @@ public:
// = Initialization method.
ACE_Module_Type (void *m, // Really an ACE_Module *.
const ACE_TCHAR *identifier,
- u_int flags = 0);
+ u_int flags = 0,
+ int stype = ACE_Service_Type::MODULE);
~ACE_Module_Type (void);
@@ -164,7 +178,8 @@ public:
// = Initialization method.
ACE_Stream_Type (void *s, // Really an ACE_Stream *.
const ACE_TCHAR *identifier,
- u_int flags = 0);
+ u_int flags = 0,
+ int stype = ACE_Service_Type::STREAM);
~ACE_Stream_Type (void);
diff --git a/ace/Service_Types.inl b/ace/Service_Types.inl
index 9ebfd705ced..02b2d3c6c41 100644
--- a/ace/Service_Types.inl
+++ b/ace/Service_Types.inl
@@ -29,4 +29,15 @@ ACE_Service_Type_Impl::name (const ACE_TCHAR *n)
this->name_ = ACE::strnew (n);
}
+ACE_INLINE int
+ACE_Service_Type_Impl::service_type (void) const
+{
+ return service_type_;
+}
+
+ACE_INLINE void
+ACE_Service_Type_Impl::service_type (int stype)
+{
+ service_type_ = stype;
+}
ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/examples/ASX/CCM_App/SC_Server.cpp b/examples/ASX/CCM_App/SC_Server.cpp
index 4a1256cf7f4..e133c3db614 100644
--- a/examples/ASX/CCM_App/SC_Server.cpp
+++ b/examples/ASX/CCM_App/SC_Server.cpp
@@ -82,5 +82,6 @@ ACE_TMAIN (int argc, ACE_TCHAR *argv[])
// Perform logging service until we receive SIGINT.
ACE_Reactor::instance ()->run_reactor_event_loop ();
+ handler.remove_stdin_handler (ACE_Reactor::instance (),ACE_Thread_Manager::instance ());
return 0;
}
diff --git a/tests/Bug_3334_Regression_Test.conf b/tests/Bug_3334_Regression_Test.conf
new file mode 100644
index 00000000000..1e863ef9fe9
--- /dev/null
+++ b/tests/Bug_3334_Regression_Test.conf
@@ -0,0 +1,7 @@
+stream dynamic Svc_Conf_Stream STREAM *Service_Config_Stream_DLL:make_stream() active
+{
+ dynamic Device_Adapter Module *Service_Config_Stream_DLL:make_da()
+ dynamic Event_Analyzer Module *Service_Config_Stream_DLL:make_ea()
+ dynamic Multicast_Router Module *Service_Config_Stream_DLL:make_mr()
+}
+
diff --git a/tests/Bug_3334_Regression_Test.cpp b/tests/Bug_3334_Regression_Test.cpp
new file mode 100644
index 00000000000..fe348154f80
--- /dev/null
+++ b/tests/Bug_3334_Regression_Test.cpp
@@ -0,0 +1,48 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = DESCRIPTION
+// This test exercises ACE_Service_Config SEGV during shutdown when
+// Modules get double deleted. Once by Stream parent,
+// once by ACE_Service_Repository
+//
+// = AUTHOR
+// Chad Beaulac <chad@objectivesolutions.com>
+//
+// ============================================================================
+
+#include "test_config.h"
+#include "ace/Log_Msg.h"
+#include "ace/Service_Config.h"
+
+ACE_RCSID(tests, Bug_3334_Regression_Test, "$Id$")
+
+int
+run_main (int, ACE_TCHAR *argv[])
+{
+ ACE_START_TEST (ACE_TEXT ("Bug_3334_Regression_Test"));
+
+ ACE_TCHAR *_argv[3] = { argv[0],
+ const_cast<ACE_TCHAR*> (ACE_TEXT ("-f")),
+ const_cast<ACE_TCHAR*>
+ (ACE_TEXT ("Bug_3334_Regression_Test.conf")) };
+ int status;
+ if ((status = ACE_Service_Config::open (3,
+ _argv,
+ ACE_DEFAULT_LOGGER_KEY,
+ true,
+ true /*ignore def svc.conf*/)) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open"),
+ 1));
+
+ ACE_Service_Config::fini_svcs ();
+
+ ACE_END_TEST;
+ return status;
+}
diff --git a/tests/Service_Config_Stream_DLL.h b/tests/Service_Config_Stream_DLL.h
new file mode 100644
index 00000000000..417ddb30894
--- /dev/null
+++ b/tests/Service_Config_Stream_DLL.h
@@ -0,0 +1,44 @@
+// $Id$
+
+#ifndef SERVICE_CONFIG_STREAM_DLL_H
+#define SERVICE_CONFIG_STREAM_DLL_H
+
+#include /**/ "ace/pre.h"
+
+#include "Service_Config_Stream_DLL_Export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Task.h"
+#include "ace/Stream.h"
+#include "ace/Module.h"
+
+typedef ACE_Task<ACE_SYNCH> MT_Task;
+typedef ACE_Stream<ACE_SYNCH> MT_Stream;
+typedef ACE_Module<ACE_SYNCH> MT_Module;
+
+class Service_Config_Stream_DLL_Export Test_Task : public MT_Task
+{
+public:
+ //FUZZ: disable check_for_lack_ACE_OS
+ virtual int open (void *);
+ virtual int close (u_long);
+ //FUZZ: enable check_for_lack_ACE_OS
+
+ virtual int init (int, ACE_TCHAR *[]);
+ virtual int fini (void);
+};
+
+// Task to verify the order and operation of the stream assembly
+// Command line args give the stream name (to look it up) and the names
+// of the tasks that should be there, from head to tail.
+class Service_Config_Stream_DLL_Export Stream_Order_Test : public MT_Task
+{
+public:
+ virtual int init (int, ACE_TCHAR *[]);
+};
+
+#include /**/ "ace/post.h"
+#endif /* SERVICE_CONFIG_STREAM_DLL_H */
diff --git a/tests/Service_Config_Stream_DLL_Export.h b/tests/Service_Config_Stream_DLL_Export.h
new file mode 100644
index 00000000000..9ef0f6caad6
--- /dev/null
+++ b/tests/Service_Config_Stream_DLL_Export.h
@@ -0,0 +1,38 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl
+// ------------------------------
+#ifndef SERVICE_CONFIG_STREAM_DLL_EXPORT_H
+#define SERVICE_CONFIG_STREAM_DLL_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (SERVICE_CONFIG_STREAM_DLL_HAS_DLL)
+# define SERVICE_CONFIG_STREAM_DLL_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! SERVICE_CONFIG_STREAM_DLL_HAS_DLL */
+
+#if !defined (SERVICE_CONFIG_STREAM_DLL_HAS_DLL)
+# define SERVICE_CONFIG_STREAM_DLL_HAS_DLL 1
+#endif /* ! TEST_HAS_DLL */
+
+#if defined (SERVICE_CONFIG_STREAM_DLL_HAS_DLL) && (SERVICE_CONFIG_STREAM_DLL_HAS_DLL == 1)
+# if defined (SERVICE_CONFIG_STREAM_DLL_BUILD_DLL)
+# define Service_Config_Stream_DLL_Export ACE_Proper_Export_Flag
+# define TEST_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* SERVICE_CONFIG_STREAM_DLL_BUILD_DLL */
+# define Service_Config_Stream_DLL_Export ACE_Proper_Import_Flag
+# define TEST_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* SERVICE_CONFIG_STREAM_DLL_BUILD_DLL */
+#else /* SERVICE_CONFIG_STREAM_DLL_HAS_DLL == 1 */
+# define Service_Config_Stream_DLL_Export
+# define TEST_SINGLETON_DECLARATION(T)
+# define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* SERVICE_CONFIG_STREAM_DLL_HAS_DLL == 1 */
+
+#endif /* SERVICE_CONFIG_STREAM_DLL_EXPORT_H */
+
+// End of auto generated file.
diff --git a/tests/Service_Config_Stream_Test.conf b/tests/Service_Config_Stream_Test.conf
new file mode 100644
index 00000000000..26128c925d0
--- /dev/null
+++ b/tests/Service_Config_Stream_Test.conf
@@ -0,0 +1,25 @@
+stream dynamic Svc_Conf_Stream STREAM *Service_Config_Stream_DLL:make_stream() active
+{
+ dynamic Device_Adapter Module *Service_Config_Stream_DLL:make_da()
+# static Decrypter
+ dynamic Event_Analyzer Module *Service_Config_Stream_DLL:make_ea()
+ dynamic Multicast_Router Module *Service_Config_Stream_DLL:make_mr()
+}
+
+#dynamic Stream_Order_Test Service_Object *Service_Config_Stream_DLL:_make_Stream_Order_Test() "Svc_Conf_Stream Multicast_Router Event_Analyzer Decrypter Device_Adapter"
+dynamic Stream_Order_Test Service_Object *Service_Config_Stream_DLL:_make_Stream_Order_Test() "Svc_Conf_Stream Multicast_Router Event_Analyzer Device_Adapter"
+
+stream Svc_Conf_Stream
+{
+ remove Device_Adapter
+ remove Event_Analyzer
+ remove Multicast_Router
+}
+#stream Svc_Conf_Stream
+#{
+# remove Decrypter
+#}
+
+remove Svc_Conf_Stream
+remove Stream_Order_Test
+
diff --git a/tests/Service_Config_Stream_Test.cpp b/tests/Service_Config_Stream_Test.cpp
new file mode 100644
index 00000000000..3ec0ab11516
--- /dev/null
+++ b/tests/Service_Config_Stream_Test.cpp
@@ -0,0 +1,131 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = DESCRIPTION
+// This test exercises ACE_Service_Config assembling a stream.
+//
+// = AUTHOR
+// Steve Huston <shuston@riverace.com>
+//
+// ============================================================================
+
+#include "test_config.h"
+#include "ace/Log_Msg.h"
+#include "ace/Module.h"
+#include "ace/Service_Config.h"
+#include "ace/Task.h"
+
+ACE_RCSID(tests, Service_Config_Stream_Test, "$Id$")
+
+/*
+ * The Decrypter service is static and is configured into a stream
+ * dynamically.
+ *
+ * NOTE! This code is here, and it will trip up while being loaded. If
+ * "static Decrypter" is inserted into the .conf file's module list, this
+ * test will barf. This is arguably a weird test, but I don't know any
+ * reason it should not work; however, this behavior has never been tested
+ * and may not have ever worked... but if someone is feeling ambitious,
+ * please go ahead and make this work. I'm out of time and energy.
+ * -Steve Huston
+ */
+class Static_Task : public ACE_Task<ACE_SYNCH>
+{
+public:
+ Static_Task() : ACE_Task<ACE_SYNCH>() {}
+
+ int open (void *)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("opening %s\n"),
+ this->name () ? this->name () : ACE_TEXT ("Static_Task")));
+ return 0;
+ }
+
+ int close (u_long)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("closing %s\n"),
+ this->name () ? this->name () : ACE_TEXT ("Static_Task")));
+ return 0;
+ }
+
+ int init (int, ACE_TCHAR *[])
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("initializing %s\n"),
+ this->name () ? this->name () : ACE_TEXT ("Static_Task")));
+ return 0;
+ }
+
+ int fini (void)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("finalizing %s\n"),
+ this->name () ? this->name () : ACE_TEXT ("Static_Task")));
+ return 0;
+ }
+};
+
+class Decrypter : public ACE_Service_Object, public ACE_Module<ACE_SYNCH>
+{
+public:
+ Decrypter ()
+ : writer_(), reader_(),
+ ACE_Module<ACE_SYNCH> (ACE_TEXT ("Decrypter"),
+ &writer_, &reader_,
+ 0,
+ M_DELETE_NONE) // Tasks are members; don't delete
+ {}
+
+private:
+ Static_Task writer_;
+ Static_Task reader_;
+};
+
+ACE_FACTORY_DEFINE (ACE_Local_Service, Decrypter)
+ACE_STATIC_SVC_DEFINE (Decrypter_Descriptor,
+ ACE_TEXT ("Decrypter"),
+ ACE_MODULE_T,
+ &ACE_SVC_NAME (Decrypter),
+ (ACE_Service_Type::DELETE_THIS |
+ ACE_Service_Type::DELETE_OBJ),
+ 1)
+ACE_STATIC_SVC_REQUIRE (Decrypter_Descriptor)
+
+
+int
+run_main (int, ACE_TCHAR *argv[])
+{
+ ACE_START_TEST (ACE_TEXT ("Service_Config_Stream_Test"));
+
+ ACE_STATIC_SVC_REGISTER (Decrypter);
+
+ // If you want to try the static module in the stream test (comments at
+ // the top of this file) it needs the -y in the argv list which enables
+ // static services. Otherwise it's not really needed. Same with the
+ // 'false' 4th arg to open() below - it allows static services.
+ ACE_TCHAR *_argv[5] = { argv[0],
+ const_cast<ACE_TCHAR*> (ACE_TEXT ("-d")),
+ const_cast<ACE_TCHAR*> (ACE_TEXT ("-y")),
+ const_cast<ACE_TCHAR*> (ACE_TEXT ("-f")),
+ const_cast<ACE_TCHAR*>
+ (ACE_TEXT ("Service_Config_Stream_Test.conf")) };
+ int status;
+ if ((status = ACE_Service_Config::open (5,
+ _argv,
+ ACE_DEFAULT_LOGGER_KEY,
+ false,
+ true /*ignore def svc.conf*/)) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open"),
+ 1));
+
+ ACE_END_TEST;
+ return status;
+}
diff --git a/tests/run_test.lst b/tests/run_test.lst
index 100cb827e71..2de272d3682 100644
--- a/tests/run_test.lst
+++ b/tests/run_test.lst
@@ -45,6 +45,7 @@ Bug_2820_Regression_Test
Bug_2980_Regression_Test: !STATIC !Win32 !VxWorks !WCHAR
Bug_3102_Regression_Test
Bug_3319_Regression_Test
+Bug_3334_Regression_Test: !STATIC
Bug_3432_Regression_Test
Bug_3500_Regression_Test
Bug_3532_Regression_Test
diff --git a/tests/tests.mpc b/tests/tests.mpc
index 9629e91fd7e..16f69453a1d 100644
--- a/tests/tests.mpc
+++ b/tests/tests.mpc
@@ -1696,3 +1696,35 @@ project(Wild_Match_Test) : acetest {
Wild_Match_Test.cpp
}
}
+
+project(Service Config Stream DLL) : acelib {
+ libout = .
+ sharedname = Service_Config_Stream_DLL
+ dynamicflags = SERVICE_CONFIG_STREAM_DLL_BUILD_DLL
+
+ Source_Files {
+ Service_Config_Stream_DLL.cpp
+ }
+ Header_Files {
+ Service_Config_Stream_DLL.h
+ Service_Config_Stream_DLL_Export.h
+ }
+ Resource_Files {
+ }
+}
+
+project(Service Config Stream Test) : acetest {
+ after += Service_Config_Stream_DLL
+ exename = Service_Config_Stream_Test
+ Source_Files {
+ Service_Config_Stream_Test.cpp
+ }
+}
+
+project(Bug_3334_Regression_Test) : acetest {
+ after += Service_Config_Stream_DLL
+ exename = Bug_3334_Regression_Test
+ Source_Files {
+ Bug_3334_Regression_Test.cpp
+ }
+}