Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Service_Config.cpp
blob9e2ca555af48707e4e8a03ebb972c9996af04ef9
1 #include "ace/Service_Config.h"
3 #if !defined (__ACE_INLINE__)
4 #include "ace/Service_Config.inl"
5 #endif /* __ACE_INLINE__ */
7 #include "ace/Service_Types.h"
8 #include "ace/Reactor.h"
9 #include "ace/Singleton.h"
10 #include "ace/Service_Repository.h"
12 #ifndef ACE_LACKS_UNIX_SIGNALS
13 # include "ace/Sig_Adapter.h"
14 #endif /* !ACE_LACKS_UNIX_SIGNALS */
16 #include "ace/OS_NS_time.h"
17 #include "ace/OS_NS_stdio.h"
18 #include "ace/OS_NS_unistd.h"
19 #include "ace/Thread.h"
20 #include "ace/Get_Opt.h"
21 #include "ace/ARGV.h"
22 #include "ace/Log_Category.h"
23 #include "ace/ACE.h"
25 #ifdef ACE_HAS_TSS_EMULATION
26 #include "ace/Object_Manager.h"
27 #endif
29 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
31 ACE_Threading_Helper<ACE_Thread_Mutex>::~ACE_Threading_Helper ()
33 ACE_OS::thr_key_detach (this->key_);
34 ACE_OS::thr_keyfree (this->key_);
37 ACE_Threading_Helper<ACE_Thread_Mutex>::ACE_Threading_Helper ()
38 : key_ (ACE_OS::NULL_key)
40 # if defined (ACE_HAS_TSS_EMULATION)
41 ACE_Object_Manager::init_tss ();
42 # endif
44 if (ACE_Thread::keycreate (&key_, 0) == -1)
46 ACELIB_ERROR ((LM_ERROR,
47 ACE_TEXT ("(%P|%t) Failed to create thread key: %p\n"),
48 ACE_TEXT ("")));
52 void
53 ACE_Threading_Helper<ACE_Thread_Mutex>::set (void* p)
55 if (ACE_Thread::setspecific (key_, p) == -1)
56 ACELIB_ERROR ((LM_ERROR,
57 ACE_TEXT ("(%P|%t) Service Config failed to set thread key value: %p\n"),
58 ACE_TEXT("")));
61 void*
62 ACE_Threading_Helper<ACE_Thread_Mutex>::get ()
64 void* temp = 0;
65 if (ACE_Thread::getspecific (key_, &temp) == -1)
66 ACELIB_ERROR_RETURN ((LM_ERROR,
67 ACE_TEXT ("(%P|%t) Service Config failed to get thread key value: %p\n"),
68 ACE_TEXT("")),
69 0);
70 return temp;
73 ACE_Threading_Helper<ACE_Null_Mutex>::~ACE_Threading_Helper ()
77 ACE_Threading_Helper<ACE_Null_Mutex>::ACE_Threading_Helper ()
81 void
82 ACE_Threading_Helper<ACE_Null_Mutex>::set (void*)
86 void*
87 ACE_Threading_Helper<ACE_Null_Mutex>::get ()
89 return ACE_Service_Config::singleton()->instance_.get ();
92 /**
93 * @c ACE_Service_Config is supposed to be a Singleton. This is the
94 * only Configuration Gestalt available for access from static
95 * initializers at proces start-up time. Using Unmanaged Singleton
96 * is safer because (a) the Object Manager may not yet be fully initialized
97 * in the context of a static initializer that uses SC, and (b) because we
98 * know that upon process exit the SC will still be automaticaly and explicitly
99 * closed by @c ACE_Object_Manager::fini().
101 using ACE_SERVICE_CONFIG_SINGLETON = ACE_Unmanaged_Singleton<ACE_Service_Config, ACE_MT_SYNCH::RECURSIVE_MUTEX>;
104 /// ctor
105 ACE_Service_Config_Guard::ACE_Service_Config_Guard (ACE_Service_Gestalt * psg)
106 : saved_ (ACE_Service_Config::current ())
108 if (ACE::debug ())
109 ACELIB_DEBUG ((LM_DEBUG,
110 ACE_TEXT ("ACE (%P|%t) - SCG:<ctor=%@>")
111 ACE_TEXT (" - config=%@ repo=%@ superseded by repo=%@\n"),
112 this,
113 this->saved_.get (),
114 this->saved_->repo_,
115 psg->repo_));
117 // Modify the TSS if the repo has changed
118 ACE_Service_Config::current (psg);
121 ACE_Service_Config_Guard::~ACE_Service_Config_Guard ()
123 ACE_Service_Gestalt* s = this->saved_.get ();
124 ACE_ASSERT (s != 0);
126 ACE_Service_Config::current (s);
128 if (ACE::debug ())
129 ACELIB_DEBUG ((LM_DEBUG,
130 ACE_TEXT ("ACE (%P|%t) SCG:<dtor=%@>")
131 ACE_TEXT (" - new repo=%@\n"),
132 this,
133 this->saved_->repo_));
137 ACE_ALLOC_HOOK_DEFINE (ACE_Service_Config)
139 // Set the signal handler to point to the handle_signal() function.
140 ACE_Sig_Adapter *ACE_Service_Config::signal_handler_ = 0;
142 // Trigger a reconfiguration.
143 sig_atomic_t ACE_Service_Config::reconfig_occurred_ = 0;
145 // = Set by command-line options.
147 /// Pathname of file to write process id.
148 ACE_TCHAR *ACE_Service_Config::pid_file_name_ = 0;
150 /// Shall we become a daemon process?
151 bool ACE_Service_Config::be_a_daemon_ = false;
153 /// Number of the signal used to trigger reconfiguration.
154 int ACE_Service_Config::signum_ = SIGHUP;
156 void
157 ACE_Service_Config::dump () const
159 #if defined (ACE_HAS_DUMP)
160 ACE_TRACE ("ACE_Service_Config::dump");
161 #endif /* ACE_HAS_DUMP */
165 ACE_Service_Config::parse_args_i (int argc, ACE_TCHAR *argv[])
167 ACE_TRACE ("ACE_Service_Config::parse_args_i");
169 // Using PERMUTE_ARGS (default) in order to have all
170 // unrecognized options and their value arguments moved
171 // to the end of the argument vector. We'll pick them up
172 // after processing our options and pass them on to the
173 // base class for further parsing.
174 //FUZZ: disable check_for_lack_ACE_OS
175 ACE_Get_Opt getopt (argc,
176 argv,
177 ACE_TEXT ("bs:p:"),
178 1 , // Start at argv[1].
179 0, // Do not report errors
180 ACE_Get_Opt::RETURN_IN_ORDER);
181 //FUZZ: enable check_for_lack_ACE_OS
183 //FUZZ: disable check_for_lack_ACE_OS
184 for (int c; (c = getopt ()) != -1; )
185 //FUZZ: enable check_for_lack_ACE_OS
186 switch (c)
188 case 'p':
189 ACE_Service_Config::pid_file_name_ = getopt.opt_arg ();
190 break;
191 case 'b':
192 ACE_Service_Config::be_a_daemon_ = true;
193 break;
194 case 's':
196 // There's no point in dealing with this on NT since it
197 // doesn't really support signals very well...
198 #if !defined (ACE_LACKS_UNIX_SIGNALS)
199 ACE_Service_Config::signum_ =
200 ACE_OS::atoi (getopt.opt_arg ());
202 if (ACE_Reactor::instance ()->register_handler
203 (ACE_Service_Config::signum_,
204 ACE_Service_Config::signal_handler_) == -1)
205 ACELIB_ERROR_RETURN ((LM_ERROR,
206 ACE_TEXT ("cannot obtain signal handler\n")),
207 -1);
208 #endif /* ACE_LACKS_UNIX_SIGNALS */
209 break;
211 default:; // unknown arguments are benign
215 return 0;
216 } /* parse_args_i () */
220 ACE_Service_Config::open_i (const ACE_TCHAR program_name[],
221 const ACE_TCHAR *logger_key,
222 bool ,
223 bool ,
224 bool )
226 ACE_TRACE ("ACE_Service_Config::open_i");
227 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
229 ACE_Log_Msg *log_msg = ACE_LOG_MSG;
231 if (ACE::debug ())
232 ACELIB_DEBUG ((LM_DEBUG,
233 ACE_TEXT ("ACE (%P|%t) SC::open_i - this=%@, opened=%d\n"),
234 this, this->is_opened_));
236 // Guard against reentrant processing.
237 if (this->is_opened_)
238 return 0;
240 this->is_opened_ = true;
242 // Check for things we need to do on a per-process basis and which
243 // may not be safe, or wise to do an a per instance basis
245 // Become a daemon before doing anything else.
246 if (ACE_Service_Config::be_a_daemon_)
248 // If we have to become a daemn and that fails
249 // return -1 here
250 if (ACE::daemonize () == -1)
251 return -1;
254 // Write process id to file.
255 if (this->pid_file_name_ != 0)
257 FILE* pidf = ACE_OS::fopen (this->pid_file_name_,
258 ACE_TEXT("w"));
260 if (pidf != 0)
262 ACE_OS::fprintf (pidf,
263 "%ld\n",
264 static_cast<long> (ACE_OS::getpid()));
265 ACE_OS::fclose (pidf);
269 u_long flags = log_msg->flags ();
271 // Only use STDERR if the caller hasn't already set the flags.
272 if (flags == 0)
273 flags = (u_long) ACE_Log_Msg::STDERR;
275 const ACE_TCHAR *key = logger_key;
277 if (key == 0 || ACE_OS::strcmp (key, ACE_DEFAULT_LOGGER_KEY) == 0)
279 // Only use the static <logger_key_> if the caller doesn't
280 // override it in the parameter list or if the key supplied is
281 // equal to the default static logger key.
282 key = ACE_Service_Config::current()->logger_key_;
284 else
286 ACE_SET_BITS (flags, ACE_Log_Msg::LOGGER);
289 if (log_msg->open (program_name,
290 flags,
291 key) == -1)
292 return -1;
294 if (ACE::debug ())
295 ACELIB_DEBUG ((LM_STARTUP,
296 ACE_TEXT ("starting up daemon %n\n")));
298 // Initialize the Service Repository (this will still work if
299 // user forgets to define an object of type ACE_Service_Config).
300 ACE_Service_Repository::instance (ACE_Service_Gestalt::MAX_SERVICES);
302 // Initialize the ACE_Reactor (the ACE_Reactor should be the
303 // same size as the ACE_Service_Repository).
304 ACE_Reactor::instance ();
306 // There's no point in dealing with this on NT since it doesn't
307 // really support signals very well...
308 #if !defined (ACE_LACKS_UNIX_SIGNALS)
309 // Only attempt to register a signal handler for positive
310 // signal numbers.
311 if (ACE_Service_Config::signum_ > 0)
313 ACE_Sig_Set ss;
314 ss.sig_add (ACE_Service_Config::signum_);
315 if ((ACE_Reactor::instance () != 0) &&
316 (ACE_Reactor::instance ()->register_handler
317 (ss, ACE_Service_Config::signal_handler_) == -1))
318 ACELIB_ERROR ((LM_ERROR,
319 ACE_TEXT ("can't register signal handler\n")));
321 #endif /* ACE_LACKS_UNIX_SIGNALS */
323 return 0;
326 /// Return the global configuration instance. Always returns the same
327 /// instance
328 ACE_Service_Config *
329 ACE_Service_Config::singleton ()
331 return ACE_SERVICE_CONFIG_SINGLETON::instance ();
335 ACE_Service_Config::insert (ACE_Static_Svc_Descriptor* stsd)
337 return ACE_Service_Config::instance ()->insert (stsd);
341 // Totally remove <svc_name> from the daemon by removing it from the
342 // ACE_Reactor, and unlinking it if necessary.
344 ACE_Service_Config::remove (const ACE_TCHAR svc_name[])
346 ACE_TRACE ("ACE_Service_Config::remove");
347 return ACE_Service_Repository::instance ()->remove (svc_name);
350 // Suspend <svc_name>. Note that this will not unlink the service
351 // from the daemon if it was dynamically linked, it will mark it as
352 // being suspended in the Service Repository and call the <suspend>
353 // member function on the appropriate <ACE_Service_Object>. A service
354 // can be resumed later on by calling the <resume> method...
357 ACE_Service_Config::suspend (const ACE_TCHAR svc_name[])
359 ACE_TRACE ("ACE_Service_Config::suspend");
360 return ACE_Service_Repository::instance ()->suspend (svc_name);
363 // Resume a SVC_NAME that was previously suspended or has not yet
364 // been resumed (e.g., a static service).
367 ACE_Service_Config::resume (const ACE_TCHAR svc_name[])
369 ACE_TRACE ("ACE_Service_Config::resume");
370 return ACE_Service_Repository::instance ()->resume (svc_name);
374 ACE_Service_Config::ACE_Service_Config (bool ignore_static_svcs,
375 size_t size,
376 int signum)
378 ACE_TRACE ("ACE_Service_Config::ACE_Service_Config");
380 // TODO: Need to find a more customizable way of instantiating the
381 // gestalt but perhaps we should leave this out untill such
382 // customizations are identified.
383 ACE_Service_Gestalt* tmp = 0;
384 ACE_NEW_NORETURN (tmp,
385 ACE_Service_Gestalt (size, false, ignore_static_svcs));
387 this->is_opened_ = false;
388 this->instance_ = tmp;
389 this->threadkey_.set (tmp);
391 ACE_Service_Config::signum_ = signum;
394 ACE_Service_Config::ACE_Service_Config (const ACE_TCHAR program_name[],
395 const ACE_TCHAR *logger_key)
397 ACE_TRACE ("ACE_Service_Config::ACE_Service_Config");
399 // TODO: Need to find a more customizable way of instantiating the
400 // gestalt but perhaps we should leave this out untill such
401 // customizations are identified.
402 ACE_Service_Gestalt* tmp = 0;
403 ACE_NEW_NORETURN (tmp,
404 ACE_Service_Gestalt (ACE_Service_Repository::DEFAULT_SIZE, false));
406 this->is_opened_ = false;
407 this->instance_ = tmp;
408 this->threadkey_.set (tmp);
410 if (this->open (program_name,
411 logger_key) == -1 && errno != ENOENT)
413 // Only print out an error if it wasn't the svc.conf file that was
414 // missing.
415 ACELIB_ERROR ((LM_ERROR,
416 ACE_TEXT ("(%P|%t) SC failed to open: %p\n"),
417 program_name));
421 /// Return the "global" configuration instance, for the current
422 /// thread. This may be the same as instance(), but on some occasions,
423 /// it may be a different one. For example, ACE_Service_Config_Guard
424 /// provides a way of temporarily replacing the "current"
425 /// configuration instance in the context of a thread.
426 ACE_Service_Gestalt*
427 ACE_Service_Config::current ()
429 void* temp = ACE_Service_Config::singleton()->threadkey_.get ();
430 if (temp == 0) {
431 // The most likely reason is that the current thread was spawned
432 // by some native primitive, like pthreads or Windows API - not
433 // from ACE. This is perfectly legal for callers who are not, or
434 // do not need to be ACE-aware. Such callers must have no
435 // expectation that the pluggable, multi-context configuration
436 // support will work - they would always get the global context,
437 // because at this point there is no information what the "parent"
438 // thread's configuration context was.
440 temp = global();
441 singleton()->threadkey_.set (temp);
444 return static_cast<ACE_Service_Gestalt*> (temp);
447 /// A mutator to set the "current" (TSS) gestalt instance.
448 void
449 ACE_Service_Config::current (ACE_Service_Gestalt* newcurrent)
451 ACE_Service_Config::singleton()->threadkey_.set (newcurrent);
455 #if (ACE_USES_CLASSIC_SVC_CONF == 0)
456 ACE_Service_Type *
457 ACE_Service_Config::create_service_type (const ACE_TCHAR *n,
458 ACE_Service_Type_Impl *o,
459 ACE_DLL &dll,
460 int active)
462 ACE_Service_Type *sp = 0;
463 ACE_NEW_RETURN (sp,
464 ACE_Service_Type (n, o, dll, active),
466 return sp;
468 #endif /* ACE_USES_CLASSIC_SVC_CONF == 0 */
470 ACE_Service_Type_Impl *
471 ACE_Service_Config::create_service_type_impl (const ACE_TCHAR *name,
472 int type,
473 void *symbol,
474 u_int flags,
475 ACE_Service_Object_Exterminator gobbler)
477 ACE_Service_Type_Impl *stp = 0;
479 // Note, the only place we need to put a case statement. This is
480 // also the place where we'd put the RTTI tests, if the compiler
481 // actually supported them!
483 switch (type)
485 case ACE_Service_Type::SERVICE_OBJECT:
486 ACE_NEW_RETURN (stp,
487 ACE_Service_Object_Type ((ACE_Service_Object *) symbol,
488 name, flags,
489 gobbler),
491 break;
492 case ACE_Service_Type::MODULE:
493 ACE_NEW_RETURN (stp,
494 ACE_Module_Type (symbol, name, flags),
496 break;
497 case ACE_Service_Type::STREAM:
498 ACE_NEW_RETURN (stp,
499 ACE_Stream_Type (symbol, name, flags),
501 break;
502 default:
503 ACELIB_ERROR ((LM_ERROR,
504 ACE_TEXT ("unknown case\n")));
505 break;
507 return stp;
511 // Signal handling API to trigger dynamic reconfiguration.
512 void
513 ACE_Service_Config::handle_signal (int sig, siginfo_t *, ucontext_t *)
515 #if defined (ACE_NDEBUG)
516 ACE_UNUSED_ARG (sig);
517 #else /* ! ACE_NDEBUG */
518 ACE_ASSERT (ACE_Service_Config::signum_ == sig);
519 #endif /* ! ACE_NDEBUG */
521 ACE_Service_Config::reconfig_occurred_ = 1;
524 // Trigger reconfiguration to re-read configuration files.
525 void
526 ACE_Service_Config::reconfigure ()
528 ACE_TRACE ("ACE_Service_Config::reconfigure");
530 ACE_Service_Config::reconfig_occurred_ = 0;
532 if (ACE::debug ())
534 #if !defined (ACE_NLOGGING)
535 time_t t = ACE_OS::time (0);
537 if (ACE::debug ())
538 ACELIB_DEBUG ((LM_DEBUG,
539 ACE_TEXT ("beginning reconfiguration at %s"),
540 ACE_OS::ctime (&t)));
541 #endif /* ! ACE_NLOGGING */
543 if (ACE_Service_Config::process_directives () == -1)
544 ACELIB_ERROR ((LM_ERROR,
545 ACE_TEXT ("%p\n"),
546 ACE_TEXT ("process_directives")));
549 // Tidy up and perform last rites on a terminating ACE_Service_Config.
551 ACE_Service_Config::close ()
553 ACE_Service_Config::singleton ()->instance_->close ();
555 // Delete the service repository. All the objects inside the
556 // service repository should already have been finalized.
557 ACE_Service_Repository::close_singleton ();
559 // Do away with the singleton ACE_Service_Config (calls dtor)
560 ACE_SERVICE_CONFIG_SINGLETON::close ();
562 return 0;
567 ACE_Service_Config::fini_svcs ()
569 ACE_TRACE ("ACE_Service_Config::fini_svcs");
571 // Clear the LM_DEBUG bit from log messages if appropriate
572 if (ACE::debug ())
573 ACE_Log_Msg::disable_debug_messages ();
575 int result = 0;
576 if (ACE_Service_Repository::instance () != 0)
577 result = ACE_Service_Repository::instance ()->fini ();
579 if (ACE::debug ())
580 ACE_Log_Msg::enable_debug_messages ();
582 return result;
585 /// Perform user-specified close activities and remove dynamic memory.
586 ACE_Service_Config::~ACE_Service_Config ()
588 ACE_TRACE ("ACE_Service_Config::~ACE_Service_Config");
591 // ************************************************************
593 /* static */
595 ACE_Service_Config::reconfig_occurred ()
597 ACE_TRACE ("ACE_Service_Config::reconfig_occurred");
598 return ACE_Service_Config::reconfig_occurred_ != 0;
601 void
602 ACE_Service_Config::reconfig_occurred (int config_occurred)
604 ACE_TRACE ("ACE_Service_Config::reconfig_occurred");
605 ACE_Service_Config::reconfig_occurred_ =
606 static_cast<sig_atomic_t> (config_occurred);
609 ACE_END_VERSIONED_NAMESPACE_DECL