summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog-97a18
-rw-r--r--ace/OS.h1
-rw-r--r--ace/OS.i14
-rw-r--r--ace/Process.cpp7
-rw-r--r--ace/Process.h19
-rw-r--r--ace/Process_Manager.cpp313
-rw-r--r--ace/Process_Manager.h93
-rw-r--r--ace/Thread_Manager.cpp26
-rw-r--r--ace/Thread_Manager.h3
-rw-r--r--examples/Threads/Makefile1
-rw-r--r--examples/Threads/process_manager.cpp145
-rw-r--r--tests/Process_Mutex_Test.cpp13
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...
diff --git a/ace/OS.h b/ace/OS.h
index dbd8d2f0fd8..6ca40edfdf1 100644
--- a/ace/OS.h
+++ b/ace/OS.h
@@ -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);
diff --git a/ace/OS.i b/ace/OS.i
index c598706338d..bcbdd108d09 100644
--- a/ace/OS.i
+++ b/ace/OS.i
@@ -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;
}