Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / examples / Threads / process_manager.cpp
blob4e9ebe88d10614d4c2d2e9905b13451bd1f1f1ba
2 //=============================================================================
3 /**
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
31 public:
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,
38 const void *arg = 0);
39 virtual int handle_close (ACE_HANDLE handle,
40 ACE_Reactor_Mask close_mask);
41 private:
42 const char *name_;
45 ExitHandler::ExitHandler (const char *name)
46 : ACE_Event_Handler (),
47 name_ (name)
51 ExitHandler::~ExitHandler ()
53 ACE_DEBUG ((LM_DEBUG,
54 "(%P|%t@%T) ExitHandler \"%s\" destroyed\n",
55 name_));
58 int
59 ExitHandler::handle_exit (ACE_Process *proc)
61 ACE_DEBUG ((LM_DEBUG,
62 "(%P|%t@%T) ExitHandler \"%s\" handle_exit for pid %d status %d\n",
63 name_,
64 proc->getpid (),
65 proc->exit_code ()));
66 return 0;
69 int
70 ExitHandler::handle_timeout(const ACE_Time_Value &,
71 const void *)
73 static int tick_tock = 0;
75 ACE_DEBUG ((LM_DEBUG,
76 "(%P|%t@%T) \"%s\" %s\n",
77 name_,
78 ACE_ODD (tick_tock) ? "Tock" : "Tick"));
79 tick_tock++;
80 return 0;
83 int
84 ExitHandler::handle_close (ACE_HANDLE,
85 ACE_Reactor_Mask)
87 ACE_DEBUG ((LM_DEBUG,
88 "(%P|%t@%T) ExitHandler \"%s\" handle_close\n",
89 name_));
90 delete this;
91 return 0;
94 // Spin furiously <iterations> times, pausing every 100 cycles to
95 // print a message and sleep for a few seconds.
97 static void
98 worker (size_t iterations)
100 for (size_t i = 0;
101 i <= iterations;
102 i++)
103 if (i && (i % 100) == 0)
105 ACE_DEBUG ((LM_DEBUG,
106 "(%P|%t@%T) worker spinning furiously... (%u)\n",
107 i));
108 ACE_OS::sleep (1);
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.
120 static void
121 parse_args (int argc, ACE_TCHAR *argv[])
123 ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("i:e:cu"));
125 int c;
127 while ((c = get_opt ()) != -1)
128 switch (c)
130 case 'i':
131 n_iterations = ACE_OS::atoi (get_opt.opt_arg ());
132 break;
133 case 'e':
134 exit_code = ACE_OS::atoi (get_opt.opt_arg ());
135 break;
136 case 'c':
137 child = 1;
138 break;
139 case 'u':
140 default:
141 ACE_DEBUG ((LM_DEBUG, "usage:\n"
142 "-p <processes>\n"
143 "-i <iterations>\n"));
144 break;
148 // Use ACE_Process_Manager::instance() to spawn another copy of this
149 // process.
151 static pid_t
152 respawn_self (const ACE_TCHAR *myname,
153 int iter,
154 int exit_code)
156 ACE_Process_Options options;
157 options.command_line ("%s -c -i %d -e %d",
158 myname,
159 iter,
160 exit_code);
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);
173 if (child)
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],
188 n_iterations,
189 111);
190 pid_t pid2 = respawn_self (argv[0],
191 n_iterations + 500,
192 222);
194 #if !defined (ACE_WIN32)
195 pid_t pid3 = ACE_OS::fork ();
197 if (!pid3)
199 worker (n_iterations);
200 return 999;
202 #endif /* ACE_WIN32 */
204 ACE_Process_Manager::instance ()->register_handler (new ExitHandler ("specific"),
205 pid2);
207 if (pid1 == ACE_INVALID_PID || pid2 == ACE_INVALID_PID)
208 ACE_ERROR_RETURN ((LM_ERROR,
209 "(%P|%t) %p\n",
210 "start_n"),
213 ACE_DEBUG ((LM_DEBUG,
214 "(%P|%t@%T) Test parent waiting (synchronously, "
215 "up to 6 seconds) for children...\n"));
217 int result =
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",
222 result));
224 if (result > 0)
226 ACE_DEBUG ((LM_DEBUG,
227 "(%P|%t@%T) Test parent waiting (synchronously, "
228 "indefinitely) for remaining children...\n"));
229 result =
230 ACE_Process_Manager::instance ()->wait ();
231 ACE_DEBUG ((LM_DEBUG,
232 "(%P|%t@%T) Test parent finished waiting: %d\n",
233 result));
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],
243 n_iterations + 200,
244 333 );
245 pid2 = respawn_self (argv[0],
246 n_iterations + 500,
247 444);
249 #if !defined (ACE_WIN32)
250 pid3 = ACE_OS::fork ();
252 if (!pid3)
254 worker (n_iterations);
255 return 888;
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,
266 ACE_Time_Value (2),
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",
280 result,
281 briefly.sec (),
282 briefly.usec ()));
284 ACE_Process_Manager::instance ()->close ();
286 return 0;