summaryrefslogtreecommitdiff
path: root/tests/Process_Manager_Test.cpp
diff options
context:
space:
mode:
authorschmidt <douglascraigschmidt@users.noreply.github.com>1999-10-13 05:00:32 +0000
committerschmidt <douglascraigschmidt@users.noreply.github.com>1999-10-13 05:00:32 +0000
commit2af7b03ad7360895d84d811d20be0fa982895ddb (patch)
treeb26c3f2be9d0144357f02d577f85c6e2a0066deb /tests/Process_Manager_Test.cpp
parent7ad4a3715227623cbfa68c01f1bb7386e366bf0d (diff)
downloadATCD-2af7b03ad7360895d84d811d20be0fa982895ddb.tar.gz
*** empty log message ***
Diffstat (limited to 'tests/Process_Manager_Test.cpp')
-rw-r--r--tests/Process_Manager_Test.cpp621
1 files changed, 161 insertions, 460 deletions
diff --git a/tests/Process_Manager_Test.cpp b/tests/Process_Manager_Test.cpp
index 5e7cf69f7d6..b290dc77ee7 100644
--- a/tests/Process_Manager_Test.cpp
+++ b/tests/Process_Manager_Test.cpp
@@ -9,39 +9,27 @@
// Process_Manager_Test.cpp
//
// = DESCRIPTION
-// This program tests the group management mechanisms provided by
-// the <ACE_Process_Manager>. In particular, it illustrates the
-// use of the following variants of the
-// <ACE_Process_Manager::wait> method:
-//
-// 1. ACE_TEST_ONE_CHILD --
+// This program tests the various methods provided by
+// <ACE_Process_Manager>. It illustrates both the explicit <wait>
+// functions and the Reactor-style auto-reaping. There's an
+// Exit_Handler class that can print out (in Debug mode) when a
+// child has been reaped.
//
-// This test uses a version of <wait> requires the parent to
-// use the signal handling mechanism in
-// <one_child_sig_handler> to keep track of the counting of
-// remaining processes. Therefore, this <wait> method is less
-// portable than the version that's used in the
-// <ACE_TEST_MULTIPLE_CHILDREN> test.
-//
-// 2. ACE_TEST_MULTIPLE_CHILDREN --
-//
-// This test uses a version of <wait> that doesn't require any
-// signal handling by the parent, i.e., it just uses one of
-// the underlying <ACE_OS::wait> methods that's portable to
-// all versions of UNIX, as well as Windows NT.
+// The child processes spawned are simply this program itself, with
+// an integer argument specifying how long to "process" (actually,
+// the child just sleeps for the specified length of time).
//
// = AUTHOR
-// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+// Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+// Dave Madden <dhm@mersenne.com>
//
// ============================================================================
#include "test_config.h"
-#include "ace/Thread_Manager.h"
#include "ace/Process_Manager.h"
-#include "ace/Signal.h"
#include "ace/Get_Opt.h"
-ACE_RCSID(tests, Process_Manager_Test, "$Id$")
+ACE_RCSID(tests, Process_Manager_Test, "Process_Manager_Test.cpp,v 4.11 1999/09/02 04:36:30 schmidt Exp")
#if defined(__BORLANDC__) && __BORLANDC__ >= 0x0530
USELIB("..\ace\aced.lib");
@@ -50,482 +38,195 @@ USELIB("..\ace\aced.lib");
#if !defined (ACE_LACKS_FORK) && defined (ACE_HAS_THREADS)
-// Global options.
-static size_t n_iterations = 100000;
+static bool debug_test = false;
-enum
+class Exit_Handler : public ACE_Event_Handler
{
- ACE_TEST_ONE_CHILD = 1,
- ACE_TEST_MULTIPLE_CHILDREN = 2
-};
+public:
+ Exit_Handler (const char *msg): msg_ (msg) { }
-// Keeps track of which of the child tests enumerated above that we're
-// running.
-static int child_test = 0;
+ virtual int handle_exit (ACE_Process *proc)
+ {
+ if (debug_test)
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%P|%t) Exit_Handler(%s) got %d: %d\n"),
+ msg_,
+ int (proc->getpid ()),
+ int (proc->exit_code ()) ));
+ return 0;
+ }
+private:
+ const char *msg_;
+};
-// Process ids of the children.
-static pid_t child_pids[ACE_MAX_PROCESSES];
+static void
+usage (const char *argv0)
+{
+ ACE_ERROR ((LM_ERROR,
+ ASYS_TEXT ("usage: %s [-d] [sleep-seconds]\n"),
+ argv0));
+ ACE_OS::exit (0);
+}
-// Coordinate the shutdown between threads.
-static ACE_Atomic_Op<ACE_Thread_Mutex, int> shut_down (0);
+static pid_t
+spawn_child (const char *argv0,
+ ACE_Process_Manager &mgr,
+ int sleep_time = 0)
+{
+ ACE_Process_Options opts;
-// This function handles signals synchronously in a separate thread of
-// control for the <ACE_TEST_ONE_CHILD> test.
+ opts.command_line ("%s %s %d",
+ argv0,
+ debug_test ? "-d" : "",
+ sleep_time);
-static void *
-one_child_sig_handler (void *)
-{
- ACE_Sig_Set sigset;
-
- // Register ourselves as a "dummy" signal handler so that this
- // processes' disposition isn't SIG_IGN (which is the default).
- ACE_Sig_Action sa ((ACE_SignalHandler) one_child_sig_handler, SIGCHLD);
- ACE_UNUSED_ARG (sa);
-
- // Register signal handlers.
- if (child_test == ACE_TEST_ONE_CHILD)
- {
- sigset.sig_add (SIGINT);
- sigset.sig_add (SIGTERM);
- }
- else
- {
- sigset.sig_add (SIGCHLD);
- sigset.sig_add (SIGHUP);
- }
+ pid_t result = mgr.spawn (opts);
- for (int result;;)
- {
- // Block waiting for SIGINT, SIGCHLD, SIGTERM, or SIGHUP,
- // depending on whether we're the parent or child process.
-
- int signum = ACE_OS::sigwait (sigset);
-
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) received signal %S\n"),
- signum));
-
- switch (signum)
- {
- case SIGINT:
- /* FALLTHRU */
- case SIGTERM:
- // Shut_Down our thread using <ACE_Thread_Manager::exit>.
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) shutting down\n")));
-
- // Signal to the main thread to shut_down.
- shut_down = 1;
-
- // Bail out.
- return 0;
- /* NOTREACHED */
-
- case SIGCHLD:
-
- for (;;)
- {
- int child_exit_status;
-
- // This method simply "reaps" the exit status of the
- // child without blocking. Note that it also decrements
- // the count of waiting children by one.
- pid_t pid =
- ACE_Process_Manager::instance ()->reap
- (-1,
- &child_exit_status,
- WNOHANG);
- // Check to see if there are anymore children to reap.
- if (pid == -1)
- break;
-
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) reaped child pid %d with exit status %d\n"),
- pid,
- child_exit_status));
- }
-
- // Bail out.
- return 0;
- /* NOTREACHED */
-
- case SIGHUP:
- // Shutdown the child.
-
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) killing child pid %d \n"),
- child_pids[0]));
- result = ACE_OS::kill (child_pids[0],
- SIGTERM);
- ACE_ASSERT (result != -1);
-
- // Continue looping on <sigwait> until the child process
- // exits.
- break;
- /* NOTREACHED */
- case -1:
- ACE_ERROR_RETURN ((LM_ERROR,
- ASYS_TEXT ("(%P|%t) %p\n"),
- "sigwait"),
- 0);
- /* NOTREACHED */
- default:
- ACE_ERROR_RETURN ((LM_ERROR,
- ASYS_TEXT ("(%P|%t) signal %S unexpected\n"),
- signum),
- 0);
- /* NOTREACHED */
- }
- }
+ if (debug_test)
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%P|%t) spawned child: %d\n"),
+ int (result)));
+ return result;
}
-// Function that runs in the child process in its own worker thread
-// for the <ACE_TEST_ONE_CHILD> test.
-
-static void *
-one_child_worker_child (void *)
+int
+main (int argc, ASYS_TCHAR *argv[])
{
- for (size_t i = 0; i < n_iterations; i++)
- {
- if (shut_down > 0)
- {
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) we've been shutdown!\n")));
- break;
- }
-
- // Every 100 iterations sleep for 2 seconds.
- if ((i % 100) == 0)
- {
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) sleeping for 2 seconds\n")));
- ACE_OS::sleep (2);
- }
-
- // After 1000 iterations sent a SIGHUP to our parent.
- if ((i % 1000) == 0)
- {
- pid_t pid = ACE_OS::getppid ();
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) sending SIGHUP to parent process %d\n"),
- pid));
- int result = ACE_OS::kill (pid, SIGHUP);
- ACE_ASSERT (result != -1);
- }
- }
+ ACE_Get_Opt args (argc, argv, "d");
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) finished running child\n")));
- return 0;
-}
-
-// This function handles signals synchronously in a separate thread of
-// control for the <ACE_TEST_MULTIPLE_CHILDREN> test.
+ for (int arg = args (); arg != EOF; arg = args ())
+ switch (arg)
+ {
+ case 'd':
+ debug_test = true;
+ break;
+ default:
+ usage (argv[0]);
+ break;
+ }
-static void *
-multiple_children_sig_handler (void *)
-{
- ACE_Sig_Set sigset;
-
- // Register signal handlers.
- if (child_test == ACE_TEST_MULTIPLE_CHILDREN)
- sigset.sig_add (SIGINT);
- else
- {
- sigset.sig_add (SIGINT);
- sigset.sig_add (SIGHUP);
+ if (args.optind == argc - 1)
+ { // child process: sleep & exit
+ int secs = atoi (argv[args.optind]);
+ ACE_OS::sleep (secs ? secs : 1);
+ if (debug_test)
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%P|%t) about to exit with code %d\n"),
+ secs));
+ ACE_OS::exit (secs);
}
- for (;;)
- {
- // Block waiting for SIGINT or SIGHUP, depending on whether
- // we're the parent or child process.
-
- int signum = ACE_OS::sigwait (sigset);
-
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) received signal %S\n"),
- signum));
-
- switch (signum)
- {
- case SIGINT:
- // Shut_Down our thread using <ACE_Thread_Manager::exit>.
- if (shut_down > 0)
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) we've been shutdown!\n")));
- else
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) hum, something weird happened...\n")));
-
- // Bail out.
- return 0;
- /* NOTREACHED */
-
- case SIGHUP:
- // Continue looping on <sigwait> until all child processes
- // exit.
- break;
- /* NOTREACHED */
-
- case -1:
- ACE_ERROR_RETURN ((LM_ERROR,
- ASYS_TEXT ("(%P|%t) %p\n"),
- "sigwait"),
- 0);
- /* NOTREACHED */
- default:
- ACE_ERROR_RETURN ((LM_ERROR,
- ASYS_TEXT ("(%P|%t) signal %S unexpected\n"),
- signum),
- 0);
- /* NOTREACHED */
- }
- }
+ if (args.optind != argc) // incorrect usage
+ usage (argv[0]);
- // @@ We never actually reach this code. Comment to fix warning.
- // return 0;
-}
+ // Try the explicit <ACE_Process_Manager::wait> functions
-// Function that runs in the child process in its own worker thread
-// for the <ACE_TEST_MULTIPLE_CHILDREN> test.
+ ACE_Process_Manager mgr;
-static void *
-multiple_children_worker_child (void *)
-{
- for (size_t i = 0; i < n_iterations; i++)
- {
- // Every 10000 iterations sleep for 1 second.
- if ((i % 10000) == 0)
- {
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) sleeping for 1 second\n")));
- ACE_OS::sleep (1);
- }
-
- // After 25000 iterations sent a SIGHUP to our parent.
- if ((i % 25000) == 0)
- {
- pid_t pid = ACE_OS::getppid ();
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) sending SIGHUP to parent process %d\n"),
- pid));
- int result = ACE_OS::kill (pid, SIGHUP);
- ACE_ASSERT (result != -1);
- }
- }
+ mgr.register_handler (new Exit_Handler ("default"));
+
+ ACE_exitcode exitcode;
- // Signal to the <sig_wait> thread to shut_down.
- shut_down = 1;
+ // wait for a specific PID
+ pid_t child1 = spawn_child (argv[0],
+ mgr,
+ 1);
+ pid_t result1 = mgr.wait (child1,
+ &exitcode);
- // Send ourselves a signal to shut down the <sigwait> thread!
- int result = ACE_OS::kill (ACE_OS::getpid (),
- SIGINT);
- ACE_ASSERT (result != -1);
+ if (debug_test)
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%P|%t) waited for child %d: %d\n"),
+ child1,
+ exitcode));
+
+ // wait for a specific PID; another should finish first
+ pid_t child2 = spawn_child (argv[0],
+ mgr,
+ 1);
+ pid_t child3 = spawn_child (argv[0],
+ mgr,
+ 4);
+ pid_t result2 = mgr.wait (child3,
+ &exitcode);
+
+ if (debug_test)
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%P|%t) waited for child %d: %d\n"),
+ child3,
+ exitcode));
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) finished running child\n")));
+ // Now wait for any...should get the one that finished earlier.
- return 0;
-}
+ pid_t result3 = mgr.wait (0,
+ &exitcode);
-// This is the driver function that spawns threads to run the various
-// tests for the parent and the child process.
+ if (debug_test)
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%P|%t) waited for any child: %d\n"),
+ exitcode));
-static void
-run_test (ACE_THR_FUNC handler,
- ACE_THR_FUNC worker)
-{
- // Block all signals.
- ACE_Sig_Set sigset (1);
- int result;
-
- result = ACE_OS::thr_sigsetmask (SIG_BLOCK,
- sigset,
- 0);
- ACE_ASSERT (result != -1);
-
- result = ACE_Thread_Manager::instance ()->spawn
- (handler, 0, THR_DETACHED);
- ACE_ASSERT (result != -1);
-
- result = ACE_Thread_Manager::instance ()->spawn
- (worker, 0, THR_DETACHED);
- ACE_ASSERT (result != -1);
-
- // Wait for all threads to finish.
- result = ACE_Thread_Manager::instance ()->wait ();
- ACE_ASSERT (result != -1);
-}
+ // Try the timed wait functions
-// This function runs the child process in a separate worker thread
-// for the <ACE_TEST_MULTIPLE_CHILDREN> test.
+ // This one shouldn't timeout:
+ pid_t child4 = spawn_child (argv[0],
+ mgr,
+ 1);
+ pid_t result4 = mgr.wait (0,
+ ACE_Time_Value (4),
+ &exitcode);
-static void *
-multiple_children_worker_parent (void *)
-{
- ACE_Process_Options options;
-
- // We're going to create a new process that runs this program
- // <ACE_MAX_PROCESSES> number of times, so we need to indicate that
- // these processes are the childen.
- options.command_line (ACE_TEXT (".")
- ACE_DIRECTORY_SEPARATOR_STR
- ACE_TEXT ("Process_Manager_Test")
- ACE_PLATFORM_EXE_SUFFIX
- ACE_TEXT (" -c 2"));
- int result =
- ACE_Process_Manager::instance ()->spawn_n (ACE_MAX_PROCESSES,
- options,
- child_pids);
- ACE_ASSERT (result != -1);
-
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) child pids =\n")));
-
- for (size_t i = 0; i < ACE_MAX_PROCESSES; i++)
+ if (debug_test)
ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("[%d]\n"),
- child_pids[i]));
-
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("\n")));
-
- // Perform a barrier wait until all our child processes have exited.
- // Note that this <wait> doesn't require any signal handling by the
- // parent, i.e., it just uses one of the underlying <ACE_OS::wait>
- // methods that's portable to all versions of UNIX, as well as
- // Windows NT.
- result = ACE_Process_Manager::instance ()->wait ();
- ACE_ASSERT (result != -1);
-
- // Signal to the <sig_wait> thread to shut_down.
- shut_down = 1;
-
- // Send ourselves a signal to shut down the <sigwait> thread!
- result = ACE_OS::kill (ACE_OS::getpid (),
- SIGINT);
- ACE_ASSERT (result != -1);
-
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) test multiple children done\n")));
- return 0;
-}
-
-// This function runs the parent process in a separate worker thread
-// for the <ACE_TEST_ONE_CHILDR> test.
+ ASYS_TEXT ("(%P|%t) waited for any child: %d\n"),
+ exitcode));
+
+ // This one should timeout:
+ pid_t child5 = spawn_child (argv[0],
+ mgr,
+ 4);
+ pid_t result5 = mgr.wait (0,
+ ACE_Time_Value (1),
+ &exitcode);
+ if (debug_test)
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%P|%t) waited for any child: %d\n"),
+ exitcode));
-static void *
-one_child_worker_parent (void *)
-{
- ACE_Process_Options options;
-
- // We're going to create a new process that runs this program again,
- // so we need to indicate that it's the child.
- options.command_line (ACE_TEXT (".")
- ACE_DIRECTORY_SEPARATOR_STR
- ACE_TEXT ("Process_Manager_Test")
- ACE_PLATFORM_EXE_SUFFIX
- ACE_TEXT (" -c 1"));
- child_pids[0] = ACE_Process_Manager::instance ()->spawn (options);
-
- ACE_ASSERT (child_pids[0] != -1);
-
- // Perform a barrier wait until all our child processes have exited.
- // Note that this <wait> requires the parent to use the signal
- // handling mechanism in <one_child_sig_handler> to keep track of
- // the counting of remaining processes. Therefore, this <wait>
- // method is less portable than the version that's shown below in
- // the <multiple_children_worker_parent> function.
- int result = ACE_Process_Manager::instance ()->wait ();
- ACE_ASSERT (result != -1);
-
- ACE_DEBUG ((LM_DEBUG,
- ASYS_TEXT ("(%P|%t) test single child done\n")));
- return 0;
-}
+ // Now wait indefinitely to clean up...
+ result5 = mgr.wait (0,
+ &exitcode);
-// Parse the command-line arguments and set options.
+ if (debug_test)
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%P|%t) waited for child 5 again: %d\n"),
+ exitcode));
-static void
-parse_args (int argc, char *argv[])
-{
- ACE_Get_Opt get_opt (argc, argv, "i:c:h");
+ // Finally, try the reactor stuff...
+ mgr.open (ACE_Process_Manager::DEFAULT_SIZE,
+ ACE_Reactor::instance ());
- int c;
+ pid_t child6 = spawn_child (argv[0],
+ mgr,
+ 5);
+ pid_t child7 = spawn_child (argv[0],
+ mgr,
+ 6);
- while ((c = get_opt ()) != -1)
- switch (c)
- {
- case 'i':
- n_iterations = ACE_OS::atoi (get_opt.optarg);
- break;
- case 'c':
- {
- int value = ACE_OS::atoi (get_opt.optarg);
- if (value == 1)
- child_test = ACE_TEST_ONE_CHILD;
- else if (value == 2)
- child_test = ACE_TEST_MULTIPLE_CHILDREN;
- else
- ACE_ERROR ((LM_ERROR,
- ASYS_TEXT ("(%P|%t) unexpected child test %d\n"),
- value));
- break;
- }
- case 'h':
- default:
- ACE_DEBUG ((LM_DEBUG,
- "(%P|%t) usage:\n"
- ASYS_TEXT ("-i <iterations>\n")));
- break;
- }
-}
+ mgr.register_handler (new Exit_Handler ("specific"),
+ child6);
-int
-main (int argc, ASYS_TCHAR *argv[])
-{
- if (argc > 1)
- {
- ACE_APPEND_LOG (ASYS_TEXT ("Process_Manager_Test-children"));
- parse_args (argc, argv);
+ ACE_Time_Value how_long (10);
- if (child_test == ACE_TEST_ONE_CHILD)
- run_test (one_child_sig_handler,
- one_child_worker_child);
+ ACE_Reactor::instance ()->run_event_loop (how_long);
- else if (child_test == ACE_TEST_MULTIPLE_CHILDREN)
- run_test (multiple_children_sig_handler,
- multiple_children_worker_child);
+ if (debug_test)
+ ACE_DEBUG ((LM_DEBUG,
+ ASYS_TEXT ("(%P|%t) done!\n") ));
- ACE_END_LOG;
- }
- else
- {
- ACE_START_TEST (ASYS_TEXT ("Process_Manager_Test"));
- ACE_INIT_LOG (ASYS_TEXT ("Process_Manager_Test-children"));
-
- // Run the parent logic for the <ACE_TEST_ONE_CHILD> test.
- run_test (one_child_sig_handler,
- one_child_worker_parent);
-
- // Run the parent logic for the <ACE_TEST_MULTIPLE_CHILDREN>
- // test.
- run_test (multiple_children_sig_handler,
- multiple_children_worker_parent);
-
- ACE_END_TEST;
- return 0;
- }
return 0;
}
-#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
-template class ACE_Atomic_Op<ACE_Thread_Mutex, int>;
-#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
-#pragma instantiate ACE_Atomic_Op<ACE_Thread_Mutex, int>
-#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
-
#else
int
main (int, ASYS_TCHAR *[])