3 //=============================================================================
5 * @file Process_Manager.h
7 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
9 //=============================================================================
11 #ifndef ACE_PROCESS_MANAGER_H
12 #define ACE_PROCESS_MANAGER_H
14 #include /**/ "ace/pre.h"
16 #include /**/ "ace/ACE_export.h"
18 #if !defined (ACE_LACKS_PRAGMA_ONCE)
20 #endif /* ACE_LACKS_PRAGMA_ONCE */
22 #include "ace/Process.h"
23 #include "ace/Event_Handler.h"
24 #include "ace/Time_Value.h"
26 #if defined (ACE_HAS_THREADS)
27 # include "ace/Recursive_Thread_Mutex.h"
28 #endif /* ACE_HAS_THREADS */
30 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
35 * @class ACE_Process_Manager
37 * @brief Manages a group of processes.
39 * This class allows applications to control groups of processes,
40 * similar to the way ACE_Thread_Manager controls groups of
41 * threads. Naturally, it doesn't work at all on platforms, such
42 * as VxWorks or pSoS, that don't support multiple processes.
43 * There are two main ways of using ACE_Process_Manager,
44 * depending on how involved you wish to be with the termination
45 * of managed processes. If you want processes to simply
46 * go away when they're finished, register the ACE_Process_Manager with
47 * an ACE_Reactor that can handle notifications of child process exit:
49 * ACE_Process_Manager mgr;
51 * mgr.open (100, ACE_Reactor::instance ());
53 * In this usage scenario, the ACE_Process_Manager will clean up after any
54 * processes that it spawns. (On Unix, this means executing a
55 * wait(2) to collect the exit status and avoid zombie
56 * processes; on Win32, it means closing the process and thread
57 * HANDLEs that are created when CreateProcess is called.)
59 * @note When you register a ACE_Process_Manager with a
60 * ACE_Reactor, the reactor's notification pipe is used to help reap the
61 * available process exit statuses. Therefore, you must not use a
62 * reactor whose notify pipe has been disabled. Here's the
63 * sequence of steps used to reap the exit statuses in this case:
64 * -# The ACE_Process_Manager registers a signal handler for
66 * -# The SIGCHLD handler, when invoked, uses the ACE_Reactor's
67 * notify() method to inform the ACE_Reactor to wake up.
68 * -# The ACE_Reactor calls the ACE_Process_Manager's
69 * handle_input() method; this happens synchronously, not in
71 * -# The handle_input() method collects all available exit
74 * If, on the other hand you want to wait "in line" to handle the
75 * terminated process cleanup code, call one of the wait functions
76 * whenever there might be managed processes that have exited.
78 * Note that in either case, ACE_Process_Manager allows you to
79 * register an ACE_Event_Handler to be called when a specific
80 * spawned process exits, or when any process without a specific
81 * ACE_Event_Handler exits. When a process exits, the
82 * appropriate ACE_Event_Handler's handle_input() method is called; the
83 * ACE_HANDLE passed is either the process's HANDLE (on Windows),
84 * or its pid cast to an ACE_HANDLE (on POSIX).
85 * It is also possible to call the wait() functions even when the
86 * ACE_Process_Manager is registered with a reactor.
88 * @note Be aware that the wait functions are "sloppy" on Unix,
89 * because there's no good way to wait for a subset of the
90 * children of a process. The wait functions may end up
91 * collecting the exit status of a process that's not managed by
92 * the ACE_Process_Manager whose wait() you invoked. It's best to
93 * only use a single ACE_Process_Manager, and to create all
94 * subprocesses by calling that manager's spawn() method.
96 class ACE_Export ACE_Process_Manager
: protected ACE_Event_Handler
99 friend class ACE_Process_Control
;
107 * @name Initialization and termination methods
111 * Initialize an ACE_Process_Manager with a table containing up to
112 * @a size processes. This table resizes itself automatically as
113 * needed. If a @a reactor is provided, this
114 * ACE_Process_Manager uses it to notify an application when a
115 * process it controls exits. By default, however, we don't use an
118 ACE_Process_Manager (size_t size
= ACE_Process_Manager::DEFAULT_SIZE
,
119 ACE_Reactor
*reactor
= 0);
122 * Initialize an ACE_Process_Manager with a table containing up to
123 * @a size processes. This table resizes itself automatically as
124 * needed. If a @a reactor is provided, this
125 * ACE_Process_Manager uses it to notify an application when a
126 * process it controls exits. By default, however, we don't use an
129 int open (size_t size
= ACE_Process_Manager::DEFAULT_SIZE
,
132 /// Release all resources. Do not wait for processes to exit.
135 /// Destructor releases all resources and does not wait for processes
137 virtual ~ACE_Process_Manager (void);
142 * @name Singleton access and control
145 /// Get pointer to a process-wide ACE_Process_Manager.
146 static ACE_Process_Manager
*instance (void);
148 /// Set pointer to a process-wide ACE_Process_Manager and return
149 /// existing pointer.
150 static ACE_Process_Manager
*instance (ACE_Process_Manager
*);
152 /// Delete the dynamically allocated singleton.
153 static void close_singleton (void);
155 /// Cleanup method, used by the ACE_Object_Manager to destroy the
157 static void cleanup (void *instance
, void *arg
);
162 * @name Process creation methods
166 * Create a new process with specified @a options.
167 * Register @a event_handler to be called back when the process exits.
168 * The @a proc object's ACE_Process::unmanage() method is called when
169 * the process is removed from ACE_Process_Manager.
171 * On success, returns the process id of the child that was created.
172 * On failure, returns ACE_INVALID_PID.
174 pid_t
spawn (ACE_Process
*proc
,
175 ACE_Process_Options
&options
,
176 ACE_Event_Handler
*event_handler
= 0);
179 * Create a new process with the specified @a options.
180 * Register @a event_handler to be called back when the process exits.
182 * On success, returns the process id of the child that was created.
183 * On failure, returns ACE_INVALID_PID.
185 pid_t
spawn (ACE_Process_Options
&options
,
186 ACE_Event_Handler
*event_handler
= 0);
189 * Create @a n new processes with the same @a options.
190 * If @a child_pids is non-0 it is expected to be an array of at least
191 * @a n pid_t, which are filled in with the process IDs of the spawned
193 * Register @a event_handler to be called back when each process exits.
194 * Returns 0 on success and -1 on failure.
196 int spawn_n (size_t n
,
197 ACE_Process_Options
&options
,
198 pid_t
*child_pids
= 0,
199 ACE_Event_Handler
*event_Handler
= 0);
203 * @name Process synchronization operations
207 * Abruptly terminate a single process with id @a pid using the
208 * ACE::terminate_process() method which works on both signal-capable
209 * systems and on Windows.
211 * @note This call is potentially dangerous to use since the process
212 * being terminated may not have a chance to cleanup before it shuts down.
213 * The process's entry is also not removed from this class's process
214 * table. Calling either wait() or remove() after terminate() is
217 * @retval 0 on success and -1 on failure.
219 int terminate (pid_t pid
);
222 * Sends the specified signal to the specified process.
224 * @note This only works on platforms that have signal capability. In
225 * particular, it doesn't work on Windows.
227 * @retval 0 on success and -1 on failure.
229 int terminate (pid_t pid
, int sig
);
232 * Block until there are no more child processes running that were
233 * spawned by this ACE_Process_Manager. Unlike the wait() method
234 * below, this method does not require a signal handler or use of
235 * ACE_OS::sigwait() because it simply blocks synchronously waiting
236 * for all the children managed by this ACE_Process_Manager to
237 * exit. Note that this does not return any status information
238 * about the success or failure of exiting child processes, although
239 * any registered exit handlers are called.
241 * @param timeout Relative time to wait for processes to terminate.
243 * @retval 0 on success; -1 on failure.
245 int wait (const ACE_Time_Value
&timeout
= ACE_Time_Value::max_time
);
246 #if defined (ACE_HAS_CPP11)
248 template< class Rep
, class Period
>
249 int wait (const std::chrono::duration
<Rep
, Period
>& timeout
)
251 ACE_Time_Value
const tv (timeout
);
252 return this->wait (tv
);
257 * Wait up to @a timeout for a single specified process to terminate.
258 * If @a pid is 0, this method waits for any of the managed processes
259 * (but see the note concerning "sloppy process cleanup on unix").
260 * If @a pid != 0, waits for that process only.
262 * @param pid Process ID
263 * @param timeout Relative time to wait for process to terminate
264 * @param status Exit status of terminated process
266 * @retval The pid of the process which exited, 0
267 * if a timeout occurred, or ACE_INVALID_PID on error.
269 pid_t
wait (pid_t pid
,
270 const ACE_Time_Value
&timeout
,
271 ACE_exitcode
*status
= 0);
272 #if defined (ACE_HAS_CPP11)
274 template< class Rep
, class Period
>
275 pid_t
wait (pid_t pid
,
276 const std::chrono::duration
<Rep
, Period
>& timeout
,
277 ACE_exitcode
*status
= 0)
279 ACE_Time_Value
const tv (timeout
);
280 return this->wait (pid
, tv
, status
);
285 * Wait indefinitely for a single, specified process to terminate.
286 * If @a pid is 0, waits for any of the managed processes (but see the
287 * note concerning "sloppy process cleanup on unix").
288 * If @a pid != 0, this method waits for that process only.
290 * @retval The pid of the process which exited, or
291 * ACE_INVALID_PID on error.
293 pid_t
wait (pid_t pid
,
294 ACE_exitcode
*status
= 0);
298 * @name Utility methods
302 * Register an event handler to be called back when the specified
303 * process exits. If @a pid == ACE_INVALID_PID this handler is called
304 * when any process with no specific handler exits.
306 * @warning In multithreaded applications, there is a race condition
307 * if a process exits between the time it is spawned and when its
308 * handler is registered. To avoid this, register the handler at
309 * the time the process is spawned.
311 int register_handler (ACE_Event_Handler
*event_handler
,
312 pid_t pid
= ACE_INVALID_PID
);
315 * Remove process @a pid from the ACE_Process_Manager's internal records.
316 * This is called automatically by the wait() method if the waited process
317 * exits. This method can also be called after calling terminate() if
318 * there's no need to wait() for the terminated process.
320 int remove (pid_t pid
);
322 /// Return the number of managed processes.
323 size_t managed (void) const;
326 * Sets the scheduling parameters for process identified by @a pid by
327 * passing @a params, @a pid to ACE_OS::sched_params().
329 * @retval 0 on success, -1 on failure, and ACE_INVALID_PID when the
330 * specified @a pid is not managed by this ACE_Process_Manager.
332 int set_scheduler (const ACE_Sched_Params
¶ms
, pid_t pid
);
335 * Sets the scheduling parameters for all the processes managed by
336 * this ACE_Process_Manager by passing @a params to
337 * ACE_OS::sched_params().
339 * @retval 0 on success, -1 on failure.
341 int set_scheduler_all (const ACE_Sched_Params
¶ms
);
343 /// Dump the state of an object.
344 void dump (void) const;
346 /// Declare the dynamic allocation hooks.
347 ACE_ALLOC_HOOK_DECLARE
;
351 // = These methods allow a <Process_Manager> to be an Event_Handler.
353 // As an Event_Handler, the <Process_Manager> automagically
354 // detects child Processes exiting and calls notify_proc_handler()
355 // and remove(). This means that you don't have to (shouldn't!)
356 // call the wait(...) methods yourself.
358 // On Unix, we can't detect individual process termination very
359 // well; the best method is to catch SIGCHLD and then call the
360 // polling wait() function to collect any available exit statuses.
361 // However, we don't want to do this from within a signal handler
362 // because of the restrictions associated. Therefore (following the
363 // lead in examples/mumble) we open a bogus handle (to ACE_DEV_NULL)
364 // and register that handle with our Reactor. Then, when our
365 // SIGCHLD handler gets invoked, we tell the Reactor that the bogus
366 // handle is readable. That will cause the handle_input() function
367 // to be called once we're out of the interrupt context, and
368 // handle_input() collects exit statuses.
370 // On Win32, we simply register ourself with the Reactor to deal
371 // with the Process handle becoming signaled. No muss, no fuss, no
372 // signal handler, and no dummy handle.
374 #if !defined(ACE_WIN32)
375 /// Collect one (or more, on unix) process exit status.
376 virtual int handle_input (ACE_HANDLE proc
);
378 /// If registered with a reactor for SIGCHLD and the reactor closes, this
379 /// will get called to notify.
380 virtual int handle_close (ACE_HANDLE handle
,
381 ACE_Reactor_Mask close_mask
);
383 #endif // !defined(ACE_WIN32)
386 * On Unix, this routine is called asynchronously when a SIGCHLD is
387 * received. We just tweak the reactor so that it'll call back our
388 * <handle_input> function, which allows us to handle Process exits
391 * On Win32, this routine is called synchronously, and is passed the
392 * HANDLE of the Process that exited, so we can do all our work here
394 virtual int handle_signal (int signum
,
401 * @struct Process_Descriptor
403 * @internal This struct is for internal use only by ACE_Process_Manager.
405 * @brief Information describing each process that's controlled by an
406 * ACE_Process_Manager.
408 struct Process_Descriptor
410 /// Default ctor/dtor.
411 Process_Descriptor (void);
412 ~Process_Descriptor (void);
414 /// Describes the process itself.
415 ACE_Process
*process_
;
417 /// Function to call when process exits
418 ACE_Event_Handler
*exit_notify_
;
420 /// Dump the state of an object.
421 void dump (void) const;
423 ACE_ALLOC_HOOK_DECLARE
;
426 /// Resize the pool of Process_Descriptors.
429 /// Locate the index of the table slot occupied by @a process_id.
430 /// Returns -1 if @a process_id is not in the @c process_table_
431 ssize_t
find_proc (pid_t process_id
);
433 #if defined (ACE_WIN32)
434 /// Locate the index of the table slot occupied by @a process_handle.
435 /// Returns ~0 if @a process_handle is not in the @c process_table_
436 ssize_t
find_proc (ACE_HANDLE process_handle
);
437 #endif /* ACE_WIN32 */
439 /// Insert a process in the table (checks for duplicates). Omitting
440 /// the process handle won't work on Win32...
441 /// Register @a event_handler to be called back when the process exits.
442 int insert_proc (ACE_Process
*process
,
443 ACE_Event_Handler
*event_handler
= 0);
446 * Append information about a process, i.e., its <process_id> in the
447 * @c process_table_. Each entry is added at the end, growing the
448 * table if necessary.
449 * Register @a event_handler to be called back when the process exits.
451 int append_proc (ACE_Process
*process
,
452 ACE_Event_Handler
*event_handler
= 0);
454 /// Actually removes the process at index @a n from the table. This method
455 /// must be called with locks held.
456 int remove_proc (size_t n
);
458 /// If there's a specific handler for the Process at index @a n in the
459 /// table, or there's a default handler, call it.
460 int notify_proc_handler (size_t n
, ACE_exitcode status
);
462 /// Vector that describes process state within the Process_Manager.
463 Process_Descriptor
*process_table_
;
465 /// Maximum number of processes we can manage (should be dynamically
467 size_t max_process_table_size_
;
469 /// Current number of processes we are managing.
470 size_t current_count_
;
472 /// This event handler is used to notify when a process we control
474 ACE_Event_Handler
*default_exit_handler_
;
476 /// Singleton pointer.
477 static ACE_Process_Manager
*instance_
;
479 /// Controls whether the <Process_Manager> is deleted when we shut
480 /// down (we can only delete it safely if we created it!)
481 static bool delete_instance_
;
483 #if defined (ACE_HAS_THREADS)
484 /// This lock protects access/ops on @c process_table_.
485 ACE_Recursive_Thread_Mutex lock_
;
486 #endif /* ACE_HAS_THREADS */
489 ACE_END_VERSIONED_NAMESPACE_DECL
491 #if defined (__ACE_INLINE__)
492 #include "ace/Process_Manager.inl"
493 #endif /* __ACE_INLINE__ */
495 #include /**/ "ace/post.h"
496 #endif /* ACE_PROCESS_MANAGER_H */