diff options
Diffstat (limited to 'ace')
-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 |
8 files changed, 209 insertions, 267 deletions
@@ -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_; |