2 //=============================================================================
4 * @file process_manager.cpp
6 * Test out the mechanisms provided by the ACE_Process_Manager.
7 * Using the global ACE_Process_Manager::instance(), we first spawn
8 * some processes (re-invoke this program, and plain-old-fork on
9 * systems that support it), and try the wait() functions.
11 * Then, we register the Process_Manager with
12 * ACE_Reactor::instance() and spawn more processes, counting on the
13 * autoreap to clean up.
15 * Specific-pid and generic exit-handler functions are also tested.
17 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu> and Dave Madden <dhm@mersenne.com>
19 //=============================================================================
22 #include "ace/OS_NS_unistd.h"
23 #include "ace/OS_main.h"
24 #include "ace/Service_Config.h"
25 #include "ace/Thread_Manager.h"
26 #include "ace/Process_Manager.h"
27 #include "ace/Get_Opt.h"
29 class ExitHandler
: public ACE_Event_Handler
32 ExitHandler (const char *name
);
34 /// Called when object is removed from the <ACE_Reactor>.
35 virtual ~ExitHandler ();
36 virtual int handle_exit (ACE_Process
*proc
);
37 virtual int handle_timeout (const ACE_Time_Value
&tv
,
39 virtual int handle_close (ACE_HANDLE handle
,
40 ACE_Reactor_Mask close_mask
);
45 ExitHandler::ExitHandler (const char *name
)
46 : ACE_Event_Handler (),
51 ExitHandler::~ExitHandler ()
54 "(%P|%t@%T) ExitHandler \"%s\" destroyed\n",
59 ExitHandler::handle_exit (ACE_Process
*proc
)
62 "(%P|%t@%T) ExitHandler \"%s\" handle_exit for pid %d status %d\n",
70 ExitHandler::handle_timeout(const ACE_Time_Value
&,
73 static int tick_tock
= 0;
76 "(%P|%t@%T) \"%s\" %s\n",
78 ACE_ODD (tick_tock
) ? "Tock" : "Tick"));
84 ExitHandler::handle_close (ACE_HANDLE
,
88 "(%P|%t@%T) ExitHandler \"%s\" handle_close\n",
94 // Spin furiously <iterations> times, pausing every 100 cycles to
95 // print a message and sleep for a few seconds.
98 worker (size_t iterations
)
103 if (i
&& (i
% 100) == 0)
105 ACE_DEBUG ((LM_DEBUG
,
106 "(%P|%t@%T) worker spinning furiously... (%u)\n",
111 ACE_DEBUG ((LM_DEBUG
,
112 "(%P|%t@%T) worker finished\n"));
115 static int n_iterations
= 500;
116 static int child
= 0;
117 static int exit_code
= 0;
119 // Parse the command-line arguments and set options.
121 parse_args (int argc
, ACE_TCHAR
*argv
[])
123 ACE_Get_Opt
get_opt (argc
, argv
, ACE_TEXT("i:e:cu"));
127 while ((c
= get_opt ()) != -1)
131 n_iterations
= ACE_OS::atoi (get_opt
.opt_arg ());
134 exit_code
= ACE_OS::atoi (get_opt
.opt_arg ());
141 ACE_DEBUG ((LM_DEBUG
, "usage:\n"
143 "-i <iterations>\n"));
148 // Use ACE_Process_Manager::instance() to spawn another copy of this
152 respawn_self (const ACE_TCHAR
*myname
,
156 ACE_Process_Options options
;
157 options
.command_line ("%s -c -i %d -e %d",
161 return ACE_Process_Manager::instance ()->spawn (options
);
165 ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
167 ACE_Service_Config daemon
;
169 daemon
.open (argv
[0]);
171 parse_args (argc
, argv
);
175 worker (n_iterations
);
177 ACE_OS::exit (exit_code
);
180 ACE_DEBUG ((LM_DEBUG
,
181 "(%P|%t@%T) Process_Manager test. Expect output from"
182 "2 or 3 processes...\n"));
184 ACE_Process_Manager::instance ()->register_handler
185 (new ExitHandler ("default"));
187 pid_t pid1
= respawn_self (argv
[0],
190 pid_t pid2
= respawn_self (argv
[0],
194 #if !defined (ACE_WIN32)
195 pid_t pid3
= ACE_OS::fork ();
199 worker (n_iterations
);
202 #endif /* ACE_WIN32 */
204 ACE_Process_Manager::instance ()->register_handler (new ExitHandler ("specific"),
207 if (pid1
== ACE_INVALID_PID
|| pid2
== ACE_INVALID_PID
)
208 ACE_ERROR_RETURN ((LM_ERROR
,
213 ACE_DEBUG ((LM_DEBUG
,
214 "(%P|%t@%T) Test parent waiting (synchronously, "
215 "up to 6 seconds) for children...\n"));
218 ACE_Process_Manager::instance ()->wait (ACE_Time_Value (6));
220 ACE_DEBUG ((LM_DEBUG
,
221 "(%P|%t@%T) Test parent: %d processes left\n",
226 ACE_DEBUG ((LM_DEBUG
,
227 "(%P|%t@%T) Test parent waiting (synchronously, "
228 "indefinitely) for remaining children...\n"));
230 ACE_Process_Manager::instance ()->wait ();
231 ACE_DEBUG ((LM_DEBUG
,
232 "(%P|%t@%T) Test parent finished waiting: %d\n",
236 ACE_DEBUG ((LM_DEBUG
,
237 "(%P|%t@%T) Test parent: try auto-reap functions\n"));
239 ACE_Process_Manager::instance ()->open (ACE_Process_Manager::DEFAULT_SIZE
,
240 ACE_Reactor::instance ());
242 pid1
= respawn_self (argv
[0],
245 pid2
= respawn_self (argv
[0],
249 #if !defined (ACE_WIN32)
250 pid3
= ACE_OS::fork ();
254 worker (n_iterations
);
257 #endif /* ACE_WIN32 */
259 ExitHandler
*main_thread_work
= 0;
260 ACE_NEW_RETURN (main_thread_work
,
261 ExitHandler ("main thread worker"),
264 ACE_Reactor::instance ()->schedule_timer (main_thread_work
,
267 ACE_Time_Value (1, 500000));
268 ACE_DEBUG ((LM_DEBUG
,
269 "(%P|%t@%T) Test parent: expect several Processes "
270 "to be auto-detected over the next 30 seconds.\n"
271 "The main thread will do some other work, too.\n" ));
273 ACE_Time_Value
briefly (30);
275 result
= ACE_Reactor::run_event_loop (briefly
);
277 ACE_DEBUG ((LM_DEBUG
,
278 "(%P|%t@%T) Test parent: finished (%d) %d.%d. Close"
279 "Process_Manager...\n",
284 ACE_Process_Manager::instance ()->close ();