00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file Process_Manager.h 00006 * 00007 * $Id: Process_Manager.h 79332 2007-08-13 20:30:44Z sowayaa $ 00008 * 00009 * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> 00010 */ 00011 //============================================================================= 00012 00013 #ifndef ACE_PROCESS_MANAGER_H 00014 #define ACE_PROCESS_MANAGER_H 00015 00016 #include /**/ "ace/pre.h" 00017 00018 #include /**/ "ace/ACE_export.h" 00019 00020 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00021 # pragma once 00022 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00023 00024 #include "ace/Process.h" 00025 #include "ace/Event_Handler.h" 00026 #include "ace/Time_Value.h" 00027 00028 #if defined (ACE_HAS_THREADS) 00029 # include "ace/Recursive_Thread_Mutex.h" 00030 #endif /* ACE_HAS_THREADS */ 00031 00032 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00033 00034 class ACE_Reactor; 00035 00036 /** 00037 * @class ACE_Process_Manager 00038 * 00039 * @brief Manages a group of processes. 00040 * 00041 * This class allows applications to control groups of processes, 00042 * similar to how the ACE_Thread_Manager controls groups of 00043 * threads. Naturally, it doesn't work at all on platforms, such 00044 * as VxWorks or pSoS, that don't support process. 00045 * There are two main ways of using ACE_Process_Manager, 00046 * depending on how involved you wish to be with the termination 00047 * of managed processes. If you want processes to simply 00048 * go away when they're finished, register the ACE_Process_Manager with 00049 * an ACE_Reactor that can handle notifications of child process exit: 00050 * @code 00051 * ACE_Process_Manager mgr; 00052 * // ... 00053 * mgr.open (100, ACE_Reactor::instance ()); 00054 * @endcode 00055 * In this usage scenario, the ACE_Process_Manager will clean up after any 00056 * processes that it spawns. (On Unix, this means executing a 00057 * wait(2) to collect the exit status and avoid zombie 00058 * processes; on Win32, it means closing the process and thread 00059 * HANDLEs that are created when CreateProcess is called.) 00060 * 00061 * @note When you register a ACE_Process_Manager with a 00062 * ACE_Reactor, the reactor's notification pipe is used to help reap the 00063 * available process exit statuses. Therefore, you must not use a 00064 * reactor whose notify pipe has been disabled. Here's the 00065 * sequence of steps used to reap the exit statuses in this case: 00066 * -# The ACE_Process_Manager registers a signal handler for 00067 * SIGCHLD. 00068 * -# The SIGCHLD handler, when invoked, uses the ACE_Reactor's 00069 * notify() method to inform the ACE_Reactor to wake up. 00070 * -# The ACE_Reactor calls the ACE_Process_Manager's 00071 * handle_input() method; this happens synchronously, not in 00072 * signal context. 00073 * -# The handle_input() method collects all available exit 00074 * statuses. 00075 * 00076 * If, on the other hand you want to wait "in line" to handle the 00077 * terminated process cleanup code, call one of the wait functions 00078 * whenever there might be managed processes that have exited. 00079 * 00080 * Note that in either case, ACE_Process_Manager allows you to 00081 * register an ACE_Event_Handler to be called when a specific 00082 * spawned process exits, or when any process without a specific 00083 * ACE_Event_Handler exits. When a process exits, the 00084 * appropriate ACE_Event_Handler's handle_input() method is called; the 00085 * ACE_HANDLE passed is either the process's HANDLE (on Win32), 00086 * or its pid cast to an ACE_HANDLE (on POSIX). 00087 * It is also possible to call the wait() functions even when the 00088 * ACE_Process_Manager is registered with a reactor. 00089 * 00090 * @note Be aware that the wait functions are "sloppy" on Unix, 00091 * because there's no good way to wait for a subset of the 00092 * children of a process. The wait functions may end up 00093 * collecting the exit status of a process that's not managed by 00094 * the ACE_Process_Manager whose wait() you invoked. It's best to 00095 * only use a single ACE_Process_Manager, and to create all 00096 * subprocesses by calling that manager's spawn() method. 00097 */ 00098 class ACE_Export ACE_Process_Manager : protected ACE_Event_Handler 00099 { 00100 public: 00101 friend class ACE_Process_Control; 00102 00103 enum 00104 { 00105 DEFAULT_SIZE = 100 00106 }; 00107 00108 /** 00109 * @name Initialization and termination methods 00110 */ 00111 //@{ 00112 /** 00113 * Initialize an ACE_Process_Manager with a table containing up to 00114 * @a size processes. This table resizes itself automatically as 00115 * needed. If a @a reactor is provided, this 00116 * ACE_Process_Manager uses it to notify an application when a 00117 * process it controls exits. By default, however, we don't use an 00118 * ACE_Reactor. 00119 */ 00120 ACE_Process_Manager (size_t size = ACE_Process_Manager::DEFAULT_SIZE, 00121 ACE_Reactor *reactor = 0); 00122 00123 /** 00124 * Initialize an ACE_Process_Manager with a table containing up to 00125 * @a size processes. This table resizes itself automatically as 00126 * needed. If a @a reactor is provided, this 00127 * ACE_Process_Manager uses it to notify an application when a 00128 * process it controls exits. By default, however, we don't use an 00129 * ACE_Reactor. 00130 */ 00131 int open (size_t size = ACE_Process_Manager::DEFAULT_SIZE, 00132 ACE_Reactor *r = 0); 00133 00134 /// Release all resources. Do not wait for processes to exit. 00135 int close (void); 00136 00137 /// Destructor releases all resources and does not wait for processes 00138 /// to exit. 00139 virtual ~ACE_Process_Manager (void); 00140 00141 //@} 00142 00143 /** 00144 * @name Singleton access and control 00145 */ 00146 //@{ 00147 /// Get pointer to a process-wide ACE_Process_Manager. 00148 static ACE_Process_Manager *instance (void); 00149 00150 /// Set pointer to a process-wide ACE_Process_Manager and return 00151 /// existing pointer. 00152 static ACE_Process_Manager *instance (ACE_Process_Manager *); 00153 00154 /// Delete the dynamically allocated singleton. 00155 static void close_singleton (void); 00156 00157 /// Cleanup method, used by the ACE_Object_Manager to destroy the 00158 /// singleton. 00159 static void cleanup (void *instance, void *arg); 00160 00161 //@} 00162 00163 /** 00164 * @name Process creation methods 00165 */ 00166 //@{ 00167 /** 00168 * Create a new process with specified @a options. 00169 * Register @a event_handler to be called back when the process exits. 00170 * 00171 * On success, returns the process id of the child that was created. 00172 * On failure, returns ACE_INVALID_PID. 00173 */ 00174 pid_t spawn (ACE_Process *proc, 00175 ACE_Process_Options &options, 00176 ACE_Event_Handler *event_handler = 0); 00177 00178 /** 00179 * Create a new process with the specified @a options. 00180 * Register @a event_handler to be called back when the process exits. 00181 * 00182 * On success, returns the process id of the child that was created. 00183 * On failure, returns ACE_INVALID_PID. 00184 */ 00185 pid_t spawn (ACE_Process_Options &options, 00186 ACE_Event_Handler *event_handler = 0); 00187 00188 /** 00189 * Create @a n new processes with the same @a options. 00190 * If @a child_pids is non-0 it is expected to be an array of at least 00191 * @a n pid_t, which are filled in with the process IDs of the spawned 00192 * processes. 00193 * Register @a event_handler to be called back when each process exits. 00194 * Returns 0 on success and -1 on failure. 00195 */ 00196 int spawn_n (size_t n, 00197 ACE_Process_Options &options, 00198 pid_t *child_pids = 0, 00199 ACE_Event_Handler *event_Handler = 0); 00200 //@} 00201 00202 /** 00203 * @name Process synchronization operations 00204 */ 00205 //@{ 00206 /** 00207 * Abruptly terminate a single process with id @a pid using the 00208 * ACE::terminate_process() method which works on both signal-capable 00209 * systems and on Windows. 00210 * 00211 * @note This call is potentially dangerous to use since the process 00212 * being terminated may not have a chance to cleanup before it shuts down. 00213 * 00214 * @retval 0 on success and -1 on failure. 00215 */ 00216 int terminate (pid_t pid); 00217 00218 /** 00219 * Sends the specified signal to the specified process. 00220 * 00221 * @note This only works on platforms that have signal capability. In 00222 * particular, it doesn't work on Windows. 00223 * 00224 * @retval 0 on success and -1 on failure. 00225 */ 00226 int terminate (pid_t pid, 00227 int sig); 00228 00229 /** 00230 * Block until there are no more child processes running that were 00231 * spawned by this ACE_Process_Manager. Unlike the wait() method 00232 * below, this method does not require a signal handler or use of 00233 * ACE_OS::sigwait() because it simply blocks synchronously waiting 00234 * for all the children managed by this ACE_Process_Manager to 00235 * exit. Note that this does not return any status information 00236 * about the success or failure of exiting child processes, although 00237 * any registered exit handlers are called. 00238 * 00239 * @param timeout Relative time to wait for processes to terminate. 00240 * 00241 * @retval 0 on success; -1 on failure. 00242 */ 00243 int wait (const ACE_Time_Value &timeout = ACE_Time_Value::max_time); 00244 00245 /** 00246 * Wait up to @a timeout for a single specified process to terminate. 00247 * If @a pid is 0, this method waits for any of the managed processes 00248 * (but see the note concerning "sloppy process cleanup on unix"). 00249 * If @a pid != 0, waits for that process only. 00250 * 00251 * @param pid Process ID 00252 * @param timeout Relative time to wait for process to terminate 00253 * @param status Exit status of terminated process 00254 * 00255 * @retval The pid of the process which exited, 0 00256 * if a timeout occurred, or ACE_INVALID_PID on error. 00257 */ 00258 pid_t wait (pid_t pid, 00259 const ACE_Time_Value &timeout, 00260 ACE_exitcode *status = 0); 00261 00262 /** 00263 * Wait indefinitely for a single, specified process to terminate. 00264 * If @a pid is 0, waits for any of the managed processes (but see the 00265 * note concerning "sloppy process cleanup on unix"). 00266 * If @a pid != 0, this method waits for that process only. 00267 * 00268 * @retval The pid of the process which exited, or 00269 * ACE_INVALID_PID on error. 00270 */ 00271 pid_t wait (pid_t pid, 00272 ACE_exitcode *status = 0); 00273 00274 /** 00275 * @deprecated 00276 * Reap the result of a single process by calling ACE_OS::waitpid(), 00277 * therefore, this method is not portable to Windows. If the child is 00278 * successfully reaped, remove() is called automatically. 00279 * Use one of the wait() methods instead of this method. 00280 */ 00281 int reap (pid_t pid = -1, 00282 ACE_exitcode *stat_loc = 0, 00283 int options = WNOHANG); 00284 //@} 00285 00286 /** 00287 * @name Utility methods 00288 */ 00289 //@{ 00290 /** 00291 * Register an event handler to be called back when the specified 00292 * process exits. If @a pid == ACE_INVALID_PID this handler is called 00293 * when any process with no specific handler exits. 00294 * 00295 * @warning In multithreaded applications, there is a race condition 00296 * if a process exits between the time it is spawned and when its 00297 * handler is registered. To avoid this, register the handler at 00298 * the time the process is spawned. 00299 */ 00300 int register_handler (ACE_Event_Handler *event_handler, 00301 pid_t pid = ACE_INVALID_PID); 00302 00303 /** 00304 * Remove process @a pid from the ACE_Process_Manager's internal records. 00305 * This is called automatically by the reap() method after it successfully 00306 * reaps a process. It's also possible to call this method 00307 * directly from a signal handler, but don't call both reap() and 00308 * remove()! 00309 */ 00310 int remove (pid_t pid); 00311 00312 /// Return the number of managed processes. 00313 size_t managed (void) const; 00314 00315 /** 00316 * Sets the scheduling parameters for process identified by @a pid by 00317 * passing @a params, @a pid to ACE_OS::sched_params(). 00318 * 00319 * @retval 0 on success, -1 on failure, and ACE_INVALID_PID when the 00320 * specified @a pid is not managed by this ACE_Process_Manager. 00321 */ 00322 int set_scheduler (const ACE_Sched_Params ¶ms, 00323 pid_t pid); 00324 00325 /** 00326 * Sets the scheduling parameters for all the processes managed by 00327 * this ACE_Process_Manager by passing @a params to 00328 * ACE_OS::sched_params(). 00329 * 00330 * @retval 0 on success, -1 on failure. 00331 */ 00332 int set_scheduler_all (const ACE_Sched_Params &); 00333 00334 /// Dump the state of an object. 00335 void dump (void) const; 00336 00337 /// Declare the dynamic allocation hooks. 00338 ACE_ALLOC_HOOK_DECLARE; 00339 //@} 00340 00341 protected: 00342 // = These methods allow a <Process_Manager> to be an <Event_Handler>. 00343 00344 // As an <Event_Handler>, the <Process_Manager> automagically 00345 // detects child Processes exiting and calls notify_proc_handler() 00346 // and remove(). This means that you don't have to (shouldn't!) 00347 // call the wait(...) methods yourself. 00348 00349 // On Unix, we can't detect individual process termination very 00350 // well; the best method is to catch SIGCHLD and then call the 00351 // polling wait() function to collect any available exit statuses. 00352 // However, we don't want to do this from within a signal handler 00353 // because of the restrictions associated. Therefore (following the 00354 // lead in examples/mumble) we open a bogus handle (to ACE_DEV_NULL) 00355 // and register that handle with our Reactor. Then, when our 00356 // SIGCHLD handler gets invoked, we tell the Reactor that the bogus 00357 // handle is readable. That will cause the handle_input() function 00358 // to be called once we're out of the interrupt context, and 00359 // handle_input() collects exit statuses. 00360 00361 // On Win32, we simply register ourself with the Reactor to deal 00362 // with the Process handle becoming signaled. No muss, no fuss, no 00363 // signal handler, and no dummy handle. 00364 00365 #if !defined(ACE_WIN32) 00366 /// Collect one (or more, on unix) process exit status. 00367 virtual int handle_input (ACE_HANDLE proc); 00368 #endif // !defined(ACE_WIN32) 00369 00370 /** 00371 * On Unix, this routine is called asynchronously when a SIGCHLD is 00372 * received. We just tweak the reactor so that it'll call back our 00373 * <handle_input> function, which allows us to handle Process exits 00374 * synchronously. 00375 * 00376 * On Win32, this routine is called synchronously, and is passed the 00377 * HANDLE of the Process that exited, so we can do all our work here 00378 */ 00379 virtual int handle_signal (int signum, 00380 siginfo_t * = 0, 00381 ucontext_t * = 0); 00382 00383 private: 00384 00385 /** 00386 * @struct Process_Descriptor 00387 * 00388 * @internal This struct is for internal use only by ACE_Process_Manager. 00389 * 00390 * @brief Information describing each process that's controlled by an 00391 * ACE_Process_Manager. 00392 */ 00393 struct Process_Descriptor 00394 { 00395 /// Default ctor/dtor. 00396 Process_Descriptor (void); 00397 ~Process_Descriptor (void); 00398 00399 /// Describes the process itself. 00400 ACE_Process *process_; 00401 00402 /// function to call when process exits 00403 ACE_Event_Handler *exit_notify_; 00404 00405 /// Dump the state of an object. 00406 void dump (void) const; 00407 }; 00408 00409 /// Resize the pool of Process_Descriptors. 00410 int resize (size_t); 00411 00412 /// Locate the index of the table slot occupied by <process_id>. 00413 /// Returns -1 if <process_id> is not in the <process_table_> 00414 ssize_t find_proc (pid_t process_id); 00415 00416 #if defined (ACE_WIN32) 00417 /// Locate the index of the table slot occupied by @a process_handle. 00418 /// Returns ~0 if @a process_handle is not in the <process_table_> 00419 ssize_t find_proc (ACE_HANDLE process_handle); 00420 #endif /* ACE_WIN32 */ 00421 00422 /// Insert a process in the table (checks for duplicates). Omitting 00423 /// the process handle won't work on Win32... 00424 /// Register @a event_handler to be called back when the process exits. 00425 int insert_proc (ACE_Process *process, 00426 ACE_Event_Handler *event_handler = 0); 00427 00428 /** 00429 * Append information about a process, i.e., its <process_id> in the 00430 * <process_table_>. Each entry is added at the end, growing the 00431 * table if necessary. 00432 * Register @a event_handler to be called back when the process exits. 00433 */ 00434 int append_proc (ACE_Process *process, 00435 ACE_Event_Handler *event_handler = 0); 00436 00437 /// Actually removes the process at index @a n from the table. This method 00438 /// must be called with locks held. 00439 int remove_proc (size_t n); 00440 00441 /// If there's a specific handler for the Process at index @a n in the 00442 /// table, or there's a default handler, call it. 00443 int notify_proc_handler (size_t n, 00444 ACE_exitcode status); 00445 00446 /// Vector that describes process state within the Process_Manager. 00447 Process_Descriptor *process_table_; 00448 00449 /// Maximum number of processes we can manage (should be dynamically 00450 /// allocated). 00451 size_t max_process_table_size_; 00452 00453 /// Current number of processes we are managing. 00454 size_t current_count_; 00455 00456 /// This event handler is used to notify when a process we control 00457 /// exits. 00458 ACE_Event_Handler *default_exit_handler_; 00459 00460 /// Singleton pointer. 00461 static ACE_Process_Manager *instance_; 00462 00463 /// Controls whether the <Process_Manager> is deleted when we shut 00464 /// down (we can only delete it safely if we created it!) 00465 static int delete_instance_; 00466 00467 #if defined (ACE_HAS_THREADS) 00468 /// This lock protects access/ops on <process_table_>. 00469 ACE_Recursive_Thread_Mutex lock_; 00470 #endif /* ACE_HAS_THREADS */ 00471 }; 00472 00473 ACE_END_VERSIONED_NAMESPACE_DECL 00474 00475 #if defined (__ACE_INLINE__) 00476 #include "ace/Process_Manager.inl" 00477 #endif /* __ACE_INLINE__ */ 00478 00479 #include /**/ "ace/post.h" 00480 #endif /* ACE_PROCESS_MANAGER_H */