Use override/default for RTPortableServer
[ACE_TAO.git] / ACE / ace / Process_Manager.h
blobb3491ff090ecd39f1140c9bfa441956bc7a5dbda
1 // -*- C++ -*-
3 //=============================================================================
4 /**
5 * @file Process_Manager.h
7 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
8 */
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)
19 # 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
32 class ACE_Reactor;
34 /**
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:
48 * @code
49 * ACE_Process_Manager mgr;
50 * // ...
51 * mgr.open (100, ACE_Reactor::instance ());
52 * @endcode
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
65 * SIGCHLD.
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
70 * signal context.
71 * -# The handle_input() method collects all available exit
72 * statuses.
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
98 public:
99 friend class ACE_Process_Control;
101 enum
103 DEFAULT_SIZE = 100
107 * @name Initialization and termination methods
109 //@{
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
116 * ACE_Reactor.
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
127 * ACE_Reactor.
129 int open (size_t size = ACE_Process_Manager::DEFAULT_SIZE,
130 ACE_Reactor *r = 0);
132 /// Release all resources. Do not wait for processes to exit.
133 int close ();
135 /// Destructor releases all resources and does not wait for processes
136 /// to exit.
137 virtual ~ACE_Process_Manager ();
139 //@}
142 * @name Singleton access and control
144 //@{
145 /// Get pointer to a process-wide ACE_Process_Manager.
146 static ACE_Process_Manager *instance ();
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 ();
155 /// Cleanup method, used by the ACE_Object_Manager to destroy the
156 /// singleton.
157 static void cleanup (void *instance, void *arg);
159 //@}
162 * @name Process creation methods
164 //@{
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
192 * processes.
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);
200 //@}
203 * @name Process synchronization operations
205 //@{
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
215 * advisable.
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);
247 /// @sa wait
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);
256 * Wait up to @a timeout for a single specified process to terminate.
257 * If @a pid is 0, this method waits for any of the managed processes
258 * (but see the note concerning "sloppy process cleanup on unix").
259 * If @a pid != 0, waits for that process only.
261 * @param pid Process ID
262 * @param timeout Relative time to wait for process to terminate
263 * @param status Exit status of terminated process
265 * @retval The pid of the process which exited, 0
266 * if a timeout occurred, or ACE_INVALID_PID on error.
268 pid_t wait (pid_t pid,
269 const ACE_Time_Value &timeout,
270 ACE_exitcode *status = 0);
272 /// @sa wait
273 template< class Rep, class Period >
274 pid_t wait (pid_t pid,
275 const std::chrono::duration<Rep, Period>& timeout,
276 ACE_exitcode *status = 0)
278 ACE_Time_Value const tv (timeout);
279 return this->wait (pid, tv, status);
283 * Wait indefinitely for a single, specified process to terminate.
284 * If @a pid is 0, waits for any of the managed processes (but see the
285 * note concerning "sloppy process cleanup on unix").
286 * If @a pid != 0, this method waits for that process only.
288 * @retval The pid of the process which exited, or
289 * ACE_INVALID_PID on error.
291 pid_t wait (pid_t pid,
292 ACE_exitcode *status = 0);
293 //@}
296 * @name Utility methods
298 //@{
300 * Register an event handler to be called back when the specified
301 * process exits. If @a pid == ACE_INVALID_PID this handler is called
302 * when any process with no specific handler exits.
304 * @warning In multithreaded applications, there is a race condition
305 * if a process exits between the time it is spawned and when its
306 * handler is registered. To avoid this, register the handler at
307 * the time the process is spawned.
309 int register_handler (ACE_Event_Handler *event_handler,
310 pid_t pid = ACE_INVALID_PID);
313 * Remove process @a pid from the ACE_Process_Manager's internal records.
314 * This is called automatically by the wait() method if the waited process
315 * exits. This method can also be called after calling terminate() if
316 * there's no need to wait() for the terminated process.
318 int remove (pid_t pid);
320 /// Return the number of managed processes.
321 size_t managed () const;
324 * Sets the scheduling parameters for process identified by @a pid by
325 * passing @a params, @a pid to ACE_OS::sched_params().
327 * @retval 0 on success, -1 on failure, and ACE_INVALID_PID when the
328 * specified @a pid is not managed by this ACE_Process_Manager.
330 int set_scheduler (const ACE_Sched_Params &params, pid_t pid);
333 * Sets the scheduling parameters for all the processes managed by
334 * this ACE_Process_Manager by passing @a params to
335 * ACE_OS::sched_params().
337 * @retval 0 on success, -1 on failure.
339 int set_scheduler_all (const ACE_Sched_Params &params);
341 /// Dump the state of an object.
342 void dump () const;
344 /// Declare the dynamic allocation hooks.
345 ACE_ALLOC_HOOK_DECLARE;
346 //@}
348 protected:
349 // = These methods allow a <Process_Manager> to be an Event_Handler.
351 // As an Event_Handler, the <Process_Manager> automagically
352 // detects child Processes exiting and calls notify_proc_handler()
353 // and remove(). This means that you don't have to (shouldn't!)
354 // call the wait(...) methods yourself.
356 // On Unix, we can't detect individual process termination very
357 // well; the best method is to catch SIGCHLD and then call the
358 // polling wait() function to collect any available exit statuses.
359 // However, we don't want to do this from within a signal handler
360 // because of the restrictions associated. Therefore (following the
361 // lead in examples/mumble) we open a bogus handle (to ACE_DEV_NULL)
362 // and register that handle with our Reactor. Then, when our
363 // SIGCHLD handler gets invoked, we tell the Reactor that the bogus
364 // handle is readable. That will cause the handle_input() function
365 // to be called once we're out of the interrupt context, and
366 // handle_input() collects exit statuses.
368 // On Win32, we simply register ourself with the Reactor to deal
369 // with the Process handle becoming signaled. No muss, no fuss, no
370 // signal handler, and no dummy handle.
372 #if !defined(ACE_WIN32)
373 /// Collect one (or more, on unix) process exit status.
374 virtual int handle_input (ACE_HANDLE proc);
376 /// If registered with a reactor for SIGCHLD and the reactor closes, this
377 /// will get called to notify.
378 virtual int handle_close (ACE_HANDLE handle,
379 ACE_Reactor_Mask close_mask);
381 #endif // !defined(ACE_WIN32)
384 * On Unix, this routine is called asynchronously when a SIGCHLD is
385 * received. We just tweak the reactor so that it'll call back our
386 * <handle_input> function, which allows us to handle Process exits
387 * synchronously.
389 * On Win32, this routine is called synchronously, and is passed the
390 * HANDLE of the Process that exited, so we can do all our work here
392 virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
394 private:
396 * @struct Process_Descriptor
398 * @internal This struct is for internal use only by ACE_Process_Manager.
400 * @brief Information describing each process that's controlled by an
401 * ACE_Process_Manager.
403 struct Process_Descriptor
405 /// Default ctor/dtor.
406 Process_Descriptor ();
407 ~Process_Descriptor ();
409 /// Describes the process itself.
410 ACE_Process *process_;
412 /// Function to call when process exits
413 ACE_Event_Handler *exit_notify_;
415 /// Dump the state of an object.
416 void dump () const;
418 ACE_ALLOC_HOOK_DECLARE;
421 /// Resize the pool of Process_Descriptors.
422 int resize (size_t);
424 /// Locate the index of the table slot occupied by @a process_id.
425 /// Returns -1 if @a process_id is not in the @c process_table_
426 ssize_t find_proc (pid_t process_id);
428 #if defined (ACE_WIN32)
429 /// Locate the index of the table slot occupied by @a process_handle.
430 /// Returns ~0 if @a process_handle is not in the @c process_table_
431 ssize_t find_proc (ACE_HANDLE process_handle);
432 #endif /* ACE_WIN32 */
434 /// Insert a process in the table (checks for duplicates). Omitting
435 /// the process handle won't work on Win32...
436 /// Register @a event_handler to be called back when the process exits.
437 int insert_proc (ACE_Process *process,
438 ACE_Event_Handler *event_handler = 0);
441 * Append information about a process, i.e., its <process_id> in the
442 * @c process_table_. Each entry is added at the end, growing the
443 * table if necessary.
444 * Register @a event_handler to be called back when the process exits.
446 int append_proc (ACE_Process *process,
447 ACE_Event_Handler *event_handler = 0);
449 /// Actually removes the process at index @a n from the table. This method
450 /// must be called with locks held.
451 int remove_proc (size_t n);
453 /// If there's a specific handler for the Process at index @a n in the
454 /// table, or there's a default handler, call it.
455 int notify_proc_handler (size_t n, ACE_exitcode status);
457 /// Vector that describes process state within the Process_Manager.
458 Process_Descriptor *process_table_;
460 /// Maximum number of processes we can manage (should be dynamically
461 /// allocated).
462 size_t max_process_table_size_;
464 /// Current number of processes we are managing.
465 size_t current_count_;
467 /// This event handler is used to notify when a process we control
468 /// exits.
469 ACE_Event_Handler *default_exit_handler_;
471 /// Singleton pointer.
472 static ACE_Process_Manager *instance_;
474 /// Controls whether the <Process_Manager> is deleted when we shut
475 /// down (we can only delete it safely if we created it!)
476 static bool delete_instance_;
478 #if defined (ACE_HAS_THREADS)
479 /// This lock protects access/ops on @c process_table_.
480 ACE_Recursive_Thread_Mutex lock_;
481 #endif /* ACE_HAS_THREADS */
484 ACE_END_VERSIONED_NAMESPACE_DECL
486 #if defined (__ACE_INLINE__)
487 #include "ace/Process_Manager.inl"
488 #endif /* __ACE_INLINE__ */
490 #include /**/ "ace/post.h"
491 #endif /* ACE_PROCESS_MANAGER_H */