diff options
-rw-r--r-- | ChangeLog-97a | 18 | ||||
-rw-r--r-- | ace/OS.h | 1 | ||||
-rw-r--r-- | ace/OS.i | 14 | ||||
-rw-r--r-- | ace/Process.cpp | 7 | ||||
-rw-r--r-- | ace/Process.h | 19 | ||||
-rw-r--r-- | ace/Process_Manager.cpp | 313 | ||||
-rw-r--r-- | ace/Process_Manager.h | 93 | ||||
-rw-r--r-- | ace/Thread_Manager.cpp | 26 | ||||
-rw-r--r-- | ace/Thread_Manager.h | 3 | ||||
-rw-r--r-- | examples/Threads/Makefile | 1 | ||||
-rw-r--r-- | examples/Threads/process_manager.cpp | 145 | ||||
-rw-r--r-- | tests/Process_Mutex_Test.cpp | 13 |
12 files changed, 381 insertions, 272 deletions
diff --git a/ChangeLog-97a b/ChangeLog-97a index 924dee9db52..3ca8690baa6 100644 --- a/ChangeLog-97a +++ b/ChangeLog-97a @@ -1,5 +1,23 @@ +Mon Apr 14 00:02:39 1997 Douglas C. Schmidt <schmidt@flamenco.cs.wustl.edu> + + * ace/Process.cpp: Replaced the use of ACE_OS::fork(void) with + ACE_OS::fork(const char *) so that we can pass in the name of + the process we're exec'ing. + + * examples/Threads/process_manager.cpp: Added a test program that + exercises the features of the new ACE_Process_Manager. + + * ace/Process_Manager: Finished a rudimentary implementation of + ACE_Process_Manager. There's still plenty of work to be done on + this, however... + + * ace/Thread_Manager.cpp (dump): Added dump() methods for + ACE_Thread_Descriptor and ACE_Thread_Manager. + Sun Apr 13 11:40:26 1997 Douglas C. Schmidt <schmidt@flamenco.cs.wustl.edu> + * ace/OS: Added a getpgid() call to ACE_OS. + * ace/Thread_Manager: Changed the 'int n' of spawn_n() to size_t n since this is more appropriate because we can't spawn a negative number of threads... @@ -2639,6 +2639,7 @@ public: // NT. argv[0] must be the full path name to the executable. static gid_t getgid (void); static pid_t getpid (void); + static pid_t getpgid (pid_t pid); static uid_t getuid (void); static pid_t setsid (void); static int system (const char *s); @@ -6137,6 +6137,20 @@ ACE_OS::getpid (void) #endif /* ACE_WIN32 */ } +ACE_INLINE pid_t +ACE_OS::getpgid (pid_t pid) +{ + // ACE_TRACE ("ACE_OS::getpid"); +#if defined (ACE_WIN32) || defined (CHORUS) + return ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) + // getpid() is not supported: just one process anyways + return 0; +#else + ACE_OSCALL_RETURN (::getpgid (pid), pid_t, -1); +#endif /* ACE_WIN32 */ +} + ACE_INLINE off_t ACE_OS::lseek (ACE_HANDLE handle, off_t offset, int whence) { diff --git a/ace/Process.cpp b/ace/Process.cpp index 76d3b5d5710..071d8eabcbb 100644 --- a/ace/Process.cpp +++ b/ace/Process.cpp @@ -53,7 +53,6 @@ ACE_Process::~ACE_Process (void) // Free resources allocated in kernel. ACE_OS::close (this->process_info_.hThread); ACE_OS::close (this->process_info_.hProcess); - #endif /* ACE_WIN32 */ } @@ -157,7 +156,7 @@ ACE_Process::start (char *argv[], char *envp[]) return -1; #else /* ACE_WIN32 */ // Fork the new process. - this->child_id_ = ACE_OS::fork (); + this->child_id_ = ACE_OS::fork (argv == 0 ? "child" : argv[1]); switch (this->child_id_) { @@ -193,9 +192,11 @@ ACE_Process::start (char *argv[], char *envp[]) // If the execv fails, this child needs to exit. ACE_OS::exit (errno); } + return 0; + /* NOTREACHED */ default: // Server process. The fork succeeded. - return 0; + return this->child_id_; } #endif /* ACE_WIN32 */ } diff --git a/ace/Process.h b/ace/Process.h index 82cc94d4b40..ac2313ae63b 100644 --- a/ace/Process.h +++ b/ace/Process.h @@ -45,15 +45,17 @@ public: ACE_HANDLE std_err = ACE_INVALID_HANDLE, char *envp[] = 0); // Set the standard handles of the new process to the respective - // handles and start the new process. <argv> must be specified. It + // handles and start the new process. If <argv> is non-NULL it // should be of the following form: argv = { - // "c:\full\path\to\foo.exe", "-a", "arg1", "etc", 0 } Returns the - // new process id on success, -1 on failure. If you want to affect - // a subset of the handles, make sure to set the others to + // "c:\full\path\to\foo.exe", "-a", "arg1", "etc", 0 }. If <argv> + // is NULL then no <exec> is performed. If <argv> is non-NULL and + // <envp> is specified, it is passed as the environment for the new + // process, according to the rules for execve(). If you want to + // affect a subset of the handles, make sure to set the others to // ACE_INVALID_HANDLE. ~ACE_Process (void); - // Death incarnate. + // Destructor. int set_handles (ACE_HANDLE std_in, ACE_HANDLE std_out = ACE_INVALID_HANDLE, @@ -67,9 +69,10 @@ public: // Set the working directory for the process. pid_t start (char *argv[], char *envp[] = 0); - // Start the new process. <argv> must be specified. It should be - // of the following form: argv = { "c:\full\path\to\foo.exe", "-a", - // "arg1", "etc", 0 }. If <envp> is specified, it is passed as the + // Start the new process. If <argv> is non-NULL it should be of the + // following form: argv = { "c:\full\path\to\foo.exe", "-a", "arg1", + // "etc", 0 }. If <argv> is NULL then no <exec> is performed. If + // <argv> is non-NULL and <envp> is specified, it is passed as the // environment for the new process, according to the rules for // execve(). Returns the new process id on success, -1 on failure. diff --git a/ace/Process_Manager.cpp b/ace/Process_Manager.cpp index 027e5b68fe9..1ee99f29703 100644 --- a/ace/Process_Manager.cpp +++ b/ace/Process_Manager.cpp @@ -9,13 +9,35 @@ #include "ace/Process_Manager.i" #endif /* __ACE_INLINE__ */ -ACE_ALLOC_HOOK_DEFINE(ACE_Process_Control) ACE_ALLOC_HOOK_DEFINE(ACE_Process_Manager) void +ACE_Process_Descriptor::dump (void) const +{ + ACE_TRACE ("ACE_Process_Descriptor::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + ACE_DEBUG ((LM_DEBUG, "\nproc_id_ = %d", this->proc_id_)); + ACE_DEBUG ((LM_DEBUG, "\ngrp_id_ = %d", this->grp_id_)); + + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +void ACE_Process_Manager::dump (void) const { ACE_TRACE ("ACE_Process_Manager::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + ACE_DEBUG ((LM_DEBUG, "\nmax_table_size_ = %d", this->max_table_size_)); + ACE_DEBUG ((LM_DEBUG, "\ncurrent_count_ = %d", this->current_count_)); + + for (size_t i = 0; i < this->current_count_; i++) + this->proc_table_[i].dump (); + + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } ACE_Process_Descriptor::ACE_Process_Descriptor (void) @@ -28,7 +50,6 @@ ACE_Process_Manager::resize (size_t size) { ACE_TRACE ("ACE_Process_Manager::resize"); - ACE_TRACE ("ACE_Thread_Manager::resize"); ACE_Process_Descriptor *temp; ACE_NEW_RETURN (temp, ACE_Process_Descriptor[size], -1); @@ -112,15 +133,27 @@ ACE_Process_Manager::start (char *argv[], // Create a new process, potentially causing an exec(), as well. // This API clearly needs to be improved to pass more information // in... - pid_t pid = ACE_Process process (argv, - ACE_INVALID_HANDLE, - ACE_INVALID_HANDLE, - ACE_INVALID_HANDLE, - envp); - if (pid == -1) - return -1; + + ACE_Process process; + + process.set_handles (ACE_INVALID_HANDLE, + ACE_INVALID_HANDLE, + ACE_INVALID_HANDLE); + + pid_t pid = process.start (argv, envp); + + // Only include the pid in the parent's table. + if (pid == -1 || pid == 0) + return pid; else - return this->append_proc (pid); + { + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + + if (this->append_proc (pid) == -1) + return -1; + else + return pid; + } } // Create N new processs running FUNC. @@ -132,20 +165,26 @@ ACE_Process_Manager::start_n (size_t n, { ACE_TRACE ("ACE_Process_Manager::spawn_n"); +#if 0 + // This doesn't work (yet). for (size_t i = 0; i < n; i++) if (this->start (argv, envp) == -1) return -1; return 0; - +#else + ACE_UNUSED_ARG (n); + ACE_UNUSED_ARG (argv); + ACE_UNUSED_ARG (envp); + ACE_NOTSUP_RETURN (-1); +#endif /* 0 */ } // Append a process into the pool (does not check for duplicates). // Must be called with locks held. int -ACE_Process_Manager::append_proc (pid_t pid, - ACE_Process_Descriptor::Process_State proc_state) +ACE_Process_Manager::append_proc (pid_t pid) { ACE_TRACE ("ACE_Process_Manager::append_proc"); @@ -156,12 +195,11 @@ ACE_Process_Manager::append_proc (pid_t pid, return -1; else { - ACE_Thread_Descriptor &proc_desc = + ACE_Process_Descriptor &proc_desc = this->proc_table_[this->current_count_]; proc_desc.proc_id_ = pid; - proc_desc.proc_id_ = - proc_desc.proc_state_ = proc_state; + proc_desc.grp_id_ = ACE_OS::getpgid (pid); this->current_count_++; return 0; @@ -172,171 +210,98 @@ ACE_Process_Manager::append_proc (pid_t pid, // allow them to be inserted twice). int -ACE_Process_Manager::insert_proc (pid_t t_id) +ACE_Process_Manager::insert_proc (pid_t pid) { ACE_TRACE ("ACE_Process_Manager::insert_proc"); - return -1; -} - -// Remove a process from the pool. Must be called with locks held. - -void -ACE_Process_Manager::remove_proc (int i) -{ - ACE_TRACE ("ACE_Process_Manager::remove_proc"); -} - -int -ACE_Process_Manager::resume_proc (int i) -{ - ACE_TRACE ("ACE_Process_Manager::resume_proc"); - return -1; -} - -int -ACE_Process_Manager::suspend_proc (int i) -{ - ACE_TRACE ("ACE_Process_Manager::suspend_proc"); - - return -1; -} - -int -ACE_Process_Manager::kill_proc (int i, int signum) -{ - ACE_TRACE ("ACE_Process_Manager::kill_proc"); - - return -1; -} - -// Locate the index in the table associated with <t_id>. Must be -// called with the lock held. - -int -ACE_Process_Manager::find (pid_t t_id) -{ - ACE_TRACE ("ACE_Process_Manager::find"); - return -1; -} -// Suspend a single process. - -int -ACE_Process_Manager::suspend (pid_t t_id) -{ - ACE_TRACE ("ACE_Process_Manager::suspend"); - return -1; -} - -// Resume a single process. - -int -ACE_Process_Manager::resume (pid_t t_id) -{ - ACE_TRACE ("ACE_Process_Manager::resume"); - return -1; -} - -// Kill a single process. -int -ACE_Process_Manager::kill (pid_t t_id, int signum) -{ - ACE_TRACE ("ACE_Process_Manager::kill"); - return -1; -} - -// Get group ids for a particular process id. - -int -ACE_Process_Manager::get_grp (pid_t t_id, int &grp_id) -{ - ACE_TRACE ("ACE_Process_Manager::get_grp"); - return -1; -} - -// Set group ids for a particular process id. +#if 0 + // Check for duplicates and bail out if they're already + // registered... + if (this->find_proc (pid) != -1) + return -1; -int -ACE_Process_Manager::set_grp (pid_t t_id, int grp_id) -{ - ACE_TRACE ("ACE_Process_Manager::set_grp"); - return -1; + return this->append_proc (pid); +#else + ACE_UNUSED_ARG (pid); + ACE_NOTSUP_RETURN (-1); +#endif } -// Suspend a group of processs. +// Remove a process from the pool. Must be called with locks held. int -ACE_Process_Manager::apply_grp (int grp_id, - PROC_FUNC func, - int arg) +ACE_Process_Manager::remove (pid_t pid) { - ACE_TRACE ("ACE_Process_Manager::apply_grp"); - return -1; -} + ACE_TRACE ("ACE_Process_Manager::remove"); -int -ACE_Process_Manager::suspend_grp (int grp_id) -{ - ACE_TRACE ("ACE_Process_Manager::suspend_grp"); - return -1; -} + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); -// Resume a group of processs. + int i = this->find_proc (pid); -int -ACE_Process_Manager::resume_grp (int grp_id) -{ - ACE_TRACE ("ACE_Process_Manager::resume_grp"); - return -1; -} + if (i == -1) + return -1; + else + { + this->current_count_--; -// Kill a group of processs. + if (this->current_count_ > 0) + // Compact the table by moving the last item into the slot vacated + // by the index being removed (this is a structure assignment). + this->proc_table_[i] = this->proc_table_[this->current_count_]; -int -ACE_Process_Manager::kill_grp (int grp_id, int signum) -{ - ACE_TRACE ("ACE_Process_Manager::kill_grp"); - return -1; +#if defined (ACE_HAS_THREADS) + // Tell all waiters when there are no more threads left in the pool. + if (this->current_count_ == 0) + this->zero_cond_.broadcast (); +#endif /* ACE_HAS_THREADS */ + return 0; + } } int -ACE_Process_Manager::apply_all (PROC_FUNC func, int arg) +ACE_Process_Manager::kill (pid_t pid, int signum) { - ACE_TRACE ("ACE_Process_Manager::apply_all"); - return -1; -} + ACE_TRACE ("ACE_Process_Manager::kill_proc"); -// Resume all processs that are suspended. + // Check for duplicates and bail out if they're already + // registered... + int i = this->find_proc (pid); -int -ACE_Process_Manager::resume_all (void) -{ - ACE_TRACE ("ACE_Process_Manager::resume_all"); - return -1; + if (i == -1) + return -1; + else + { + int result = ACE_OS::kill (this->proc_table_[i].proc_id_, + signum); + + if (result == -1) + { + // We need to save this across calls to remove_thr() since that + // call may reset errno. + int error = errno; + + this->remove (this->proc_table_[i].proc_id_); + errno = error; + return -1; + } + else + return 0; + } } -int -ACE_Process_Manager::suspend_all (void) -{ - ACE_TRACE ("ACE_Process_Manager::suspend_all"); - return -1; -} +// Locate the index in the table associated with <pid>. Must be +// called with the lock held. int -ACE_Process_Manager::kill_all (int sig) +ACE_Process_Manager::find_proc (pid_t pid) { - ACE_TRACE ("ACE_Process_Manager::kill_all"); - return -1; -} + ACE_TRACE ("ACE_Process_Manager::find_proc"); -// Must be called when process goes out of scope to clean up its table -// slot. + for (size_t i = 0; i < this->current_count_; i++) + if (pid == this->proc_table_[i].proc_id_) + return i; -void * -ACE_Process_Manager::exit (void *status) -{ - ACE_TRACE ("ACE_Process_Manager::exit"); - return 0; + return -1; } // Wait for all the processs to exit. @@ -345,36 +310,30 @@ int ACE_Process_Manager::wait (ACE_Time_Value *timeout) { ACE_TRACE ("ACE_Process_Manager::wait"); - return -1; -} -void -ACE_Process_Control::dump (void) const -{ - ACE_TRACE ("ACE_Process_Control::dump"); -} +#if defined (ACE_HAS_THREADS) + ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1); -// Initialize the process controller. + while (this->current_count_ > 0) + if (this->zero_cond_.wait (timeout) == -1) + return -1; +#else + ACE_UNUSED_ARG (timeout); +#endif /* ACE_HAS_THREADS */ -ACE_Process_Control::ACE_Process_Control (ACE_Process_Manager *t, - int insert) -{ - ACE_TRACE ("ACE_Process_Control::ACE_Process_Control"); + return 0; } -// Automatically kill process on exit. +// Reap a <SIGCHLD> by calling <ACE_OS::waitpid>. -ACE_Process_Control::~ACE_Process_Control (void) +int +ACE_Process_Manager::reap (pid_t pid, int *stat_loc, int options) { - ACE_TRACE ("ACE_Process_Control::~ACE_Process_Control"); -} + ACE_TRACE ("ACE_Process_Manager::reap"); -// Exit from process (but clean up first). + pid = ACE_OS::waitpid (pid, stat_loc, options); -void * -ACE_Process_Control::exit (void *exit_status) -{ - ACE_TRACE ("ACE_Process_Control::exit"); - return 0; + if (pid != -1) + this->remove (pid); + return pid; } - diff --git a/ace/Process_Manager.h b/ace/Process_Manager.h index 96896b96a4b..651d236c097 100644 --- a/ace/Process_Manager.h +++ b/ace/Process_Manager.h @@ -24,14 +24,6 @@ class ACE_Export ACE_Process_Descriptor // Information for controlling groups of processs. { friend class ACE_Process_Manager; -public: - enum Process_State - { - IDLE, - SPAWNED, - RUNNING, - TERMINATED - }; private: ACE_Process_Descriptor (void); @@ -42,14 +34,10 @@ private: gid_t grp_id_; // Unique group ID. - Process_State proc_state_; - // Current state of the process. + void dump (void) const; + // Dump the state of an object. }; -// Forward declaration. - -class ACE_Process_Control; - class ACE_Export ACE_Process_Manager // = TITLE // Manages a pool of processs. @@ -92,17 +80,15 @@ public: // Block until there are no more processs running or <timeout> // expires. Returns 0 on success and -1 on failure. - // = Kill methods (send signals...). - int kill_all (int signum); - // Send signum to all stopped processs int kill (pid_t, int signum); // Kill a single process. - int kill_grp (int grp_id, int signum); - // Kill a group of processs. - // = Set/get group ids for a particular process id. - int set_grp (pid_t, int grp_id); - int get_grp (pid_t, int &grp_id); + int remove (pid_t pid); + // Remove process <pid> from the table. This is typically called by + // a signal handler that has just reaped <SIGCHILD>. + + int reap (pid_t pid = -1, int *stat_loc = 0, int options = WNOHANG); + // Reap a <SIGCHLD> by calling <ACE_OS::waitpid>. void dump (void) const; // Dump the state of an object. @@ -114,7 +100,7 @@ private: int resize (size_t); // Resize the pool of Process_Descriptors. - int find (pid_t p_id); + int find_proc (pid_t p_id); // Locate the index of the table slot occupied by <p_id>. Returns // -1 if <p_id> is not in the table doesn't contain <p_id>. @@ -122,27 +108,10 @@ private: // Insert a process in the table (checks for duplicates). // Omitting the process handle won't work on Win32... - int append_proc (pid_t p_id, ACE_Process_Descriptor::Process_State); + int append_proc (pid_t p_id); // Append a process in the table (adds at the end, growing the table // if necessary). - void remove_proc (int i); - // Remove process from the table. - - // = The following four methods implement a simple scheme for - // operating on a collection of processs atomically. - - typedef int (ACE_Process_Manager::*PROC_FUNC)(int, int); - - int apply_grp (int grp_id, PROC_FUNC, int = 0); - // Apply <func> to all members of the table that match the <grp_id>. - - int apply_all (PROC_FUNC, int = 0); - // Apply <func> to all members of the table. - - int kill_proc (int i, int signum); - // Send signal <signum> to the process at index <i>. - ACE_Process_Descriptor *proc_table_; // Vector that describes process state within the Process_Manager. @@ -152,44 +121,12 @@ private: size_t current_count_; // Current number of processs we are managing. -}; - -class ACE_Export ACE_Process_Control - // = TITLE - // Used to keep track of a process's activities within its entry - // point function. -{ -public: - ACE_Process_Control (ACE_Process_Manager *tm, int insert = 0); - // Initialize the process control object. If INSERT != 0, then - // register the process with the ProcessManager. - - ~ACE_Process_Control (void); - // Implicitly kill the process on exit and remove it from its - // associated ProcessManager. - - void *exit (void *status); - // Explicitly kill the process on exit and remove it from its - // associated ProcessManager. - - void *status (void *status); - // Set the exit status (and return existing status). - - void *status (void); - // Get the current exit status. - - void dump (void) const; - // Dump the state of an object. - - ACE_ALLOC_HOOK_DECLARE; - // Declare the dynamic allocation hooks. - -private: - ACE_Process_Manager *tm_; - // Pointer to the process manager for this block of code. - void *status_; - // Keeps track of the exit status for the process. + // = ACE_Thread_Mutex and condition variable for synchronizing termination. +#if defined (ACE_HAS_THREADS) + ACE_Thread_Mutex lock_; + ACE_Condition_Thread_Mutex zero_cond_; +#endif /* ACE_HAS_THREADS */ }; #if defined (__ACE_INLINE__) diff --git a/ace/Thread_Manager.cpp b/ace/Thread_Manager.cpp index 4ea8f97baf0..686d24afef0 100644 --- a/ace/Thread_Manager.cpp +++ b/ace/Thread_Manager.cpp @@ -15,6 +15,30 @@ void ACE_Thread_Manager::dump (void) const { ACE_TRACE ("ACE_Thread_Manager::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + ACE_DEBUG ((LM_DEBUG, "\ngrp_id_ = %d", this->grp_id_)); + ACE_DEBUG ((LM_DEBUG, "\nmax_table_size_ = %d", this->max_table_size_)); + ACE_DEBUG ((LM_DEBUG, "\ncurrent_count_ = %d", this->current_count_)); + + for (size_t i = 0; i < this->current_count_; i++) + this->thr_table_[i].dump (); + + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +void +ACE_Thread_Descriptor::dump (void) const +{ + ACE_TRACE ("ACE_Thread_Descriptor::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + ACE_DEBUG ((LM_DEBUG, "\nthr_id_ = %d", this->thr_id_)); + ACE_DEBUG ((LM_DEBUG, "\nthr_handle_ = %d", this->thr_handle_)); + ACE_DEBUG ((LM_DEBUG, "\ngrp_id_ = %d", this->grp_id_)); + ACE_DEBUG ((LM_DEBUG, "\nthr_state_ = %d", this->thr_state_)); + + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } ACE_Thread_Descriptor::ACE_Thread_Descriptor (void) @@ -225,7 +249,7 @@ ACE_Thread_Manager::spawn (ACE_THR_FUNC func, // Create N new threads running FUNC. int -ACE_Thread_Manager::spawn_n (int n, +ACE_Thread_Manager::spawn_n (size_t n, ACE_THR_FUNC func, void *args, long flags, diff --git a/ace/Thread_Manager.h b/ace/Thread_Manager.h index 83a5528d279..ccba91ad235 100644 --- a/ace/Thread_Manager.h +++ b/ace/Thread_Manager.h @@ -50,6 +50,9 @@ public: ACE_Task_Base *task_; // Pointer to an ACE_Task; + void dump (void) const; + // Dump the state of an object. + private: ACE_thread_t thr_id_; diff --git a/examples/Threads/Makefile b/examples/Threads/Makefile index e1e41570dfa..0911f9d7c0c 100644 --- a/examples/Threads/Makefile +++ b/examples/Threads/Makefile @@ -14,6 +14,7 @@ BIN = auto_event \ future1 \ future2 \ manual_event \ + process_manager \ process_mutex \ process_semaphore \ reader_writer \ diff --git a/examples/Threads/process_manager.cpp b/examples/Threads/process_manager.cpp new file mode 100644 index 00000000000..b8499b8056a --- /dev/null +++ b/examples/Threads/process_manager.cpp @@ -0,0 +1,145 @@ +// $Id$ + +// Test out the mechanisms provided by the ACE_Process_Manager. + +#include "ace/Service_Config.h" +#include "ace/Process_Manager.h" + +#if !defined (ACE_WIN32) && defined (ACE_HAS_THREADS) + +// Global process manager. +static ACE_Process_Manager proc_mgr; + +void * +sig_handler (void *) +{ + ACE_Thread_Control tc (ACE_Service_Config::thr_mgr ()); + + ACE_Sig_Set sigset; + + // Register a dummy signal handler so that our disposition isn't + // SIG_IGN (which is the default). + ACE_Sig_Action sa ((ACE_SignalHandler) sig_handler, SIGCHLD); + ACE_UNUSED_ARG (sa); + + // Register signal handlers. + sigset.sig_add (SIGINT); + sigset.sig_add (SIGCHLD); + + for (;;) + { + int signum = ACE_OS::sigwait (sigset); + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) received signal %S\n", + signum)); + + switch (signum) + { + case SIGINT: + // Shutdown using <ACE_OS::exit>. + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) shutting down %n%a\n", 1)); + /* NOTREACHED */ + case SIGCHLD: + + for (;;) + { + pid_t pid = proc_mgr.reap (); + + switch (pid) + { + case -1: + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", "reap"), 0); + /* NOTREACHED */ + default: + ACE_DEBUG ((LM_DEBUG, "(%P|%t) reaped pid %d\n", pid)); + } + } + + break; + case -1: + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "sigwait"), 0); + /* NOTREACHED */ + default: + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) signal %S unexpected\n", signum), 0); + /* NOTREACHED */ + } + } +} + +static void +worker (size_t iterations) +{ + for (size_t i = 0; i < iterations; i++) + if ((i % 100) == 0) + { + ACE_DEBUG ((LM_DEBUG, "(%P|%t) sleeping\n")); + ACE_OS::sleep (5); + } +} + +extern "C" void +exithook (void) +{ + ACE_DEBUG ((LM_DEBUG, "(%P|%t) later...\n")); +} + +static const int DEFAULT_THREADS = ACE_DEFAULT_THREADS; +static const int DEFAULT_ITERATIONS = 100000; + +int +main (int argc, char *argv[]) +{ + ACE_Service_Config daemon; + + daemon.open (argv[0]); + + ::atexit (exithook); + + ACE_Sig_Set sigset (1); // Block all signals. + + if (ACE_OS::thr_sigsetmask (SIG_BLOCK, sigset, 0) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "thr_sigsetmask"), 1); + else if (ACE_Service_Config::thr_mgr ()->spawn (sig_handler, 0, THR_DETACHED) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn"), 1); + + int n_processes = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_THREADS; + ACE_UNUSED_ARG (n_processes); + int n_iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : DEFAULT_ITERATIONS; + + pid_t pid = proc_mgr.start (0); + + switch (pid) + { + case -1: + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", "start_n"), 1); + /* NOTREACHED */ + case 0: + worker (n_iterations); + break; + /* NOTREACHED */ + default: + // Give the child a chance to start running. + ACE_OS::sleep (1); + + // Shutdown the child. + if (proc_mgr.kill (pid, SIGINT) == -1) + ACE_ERROR_RETURN ((LM_DEBUG, "(%P|%t) %p\n", "kill"), 1); + + // Perform a barrier wait until all the processes and threads + // have shut down. + proc_mgr.wait (); + ACE_Service_Config::thr_mgr ()->wait (); + } + + return 0; +} +#else +int +main (int, char *[]) +{ + ACE_ERROR_RETURN ((LM_ERROR, "process manager not supported on this platform\n"), -1); +} +#endif /* !ACE_WIN32 && ACE_HAS_THREADS */ diff --git a/tests/Process_Mutex_Test.cpp b/tests/Process_Mutex_Test.cpp index 2cf2ee5913f..bb02f0bcc04 100644 --- a/tests/Process_Mutex_Test.cpp +++ b/tests/Process_Mutex_Test.cpp @@ -108,23 +108,26 @@ main (int argc, char *argv[]) s_argv[4] = 0; s_argv[5] = 0; - // Spawn ACE_MAX_PROCESSES processes which will contend for the + // Spawn ACE_MAX_PROCESSES processes that will contend for the // lock. ACE_Process servers[ACE_MAX_PROCESSES]; - int i; + size_t i; for (i = 0; i < ACE_MAX_PROCESSES; i++) { ACE_ASSERT (servers[i].start (s_argv) != -1); - - ACE_DEBUG ((LM_DEBUG, "Server forked with pid = %d.\n", servers[i].getpid ())); + ACE_DEBUG ((LM_DEBUG, + "Server forked with pid = %d.\n", + servers[i].getpid ())); } for (i = 0; i < ACE_MAX_PROCESSES; i++) { // Wait for the process we created to exit. ACE_ASSERT (servers[i].wait () != -1); - ACE_DEBUG ((LM_DEBUG, "Server %d finished\n", servers[i].getpid ())); + ACE_DEBUG ((LM_DEBUG, + "Server %d finished\n", + servers[i].getpid ())); } ACE_END_TEST; } |