00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file Process_Manager.h 00006 * 00007 * $Id: Process_Manager.h 81014 2008-03-19 11:41:31Z johnnyw $ 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, int sig); 00227 00228 /** 00229 * Block until there are no more child processes running that were 00230 * spawned by this ACE_Process_Manager. Unlike the wait() method 00231 * below, this method does not require a signal handler or use of 00232 * ACE_OS::sigwait() because it simply blocks synchronously waiting 00233 * for all the children managed by this ACE_Process_Manager to 00234 * exit. Note that this does not return any status information 00235 * about the success or failure of exiting child processes, although 00236 * any registered exit handlers are called. 00237 * 00238 * @param timeout Relative time to wait for processes to terminate. 00239 * 00240 * @retval 0 on success; -1 on failure. 00241 */ 00242 int wait (const ACE_Time_Value &timeout = ACE_Time_Value::max_time); 00243 00244 /** 00245 * Wait up to @a timeout for a single specified process to terminate. 00246 * If @a pid is 0, this method waits for any of the managed processes 00247 * (but see the note concerning "sloppy process cleanup on unix"). 00248 * If @a pid != 0, waits for that process only. 00249 * 00250 * @param pid Process ID 00251 * @param timeout Relative time to wait for process to terminate 00252 * @param status Exit status of terminated process 00253 * 00254 * @retval The pid of the process which exited, 0 00255 * if a timeout occurred, or ACE_INVALID_PID on error. 00256 */ 00257 pid_t wait (pid_t pid, 00258 const ACE_Time_Value &timeout, 00259 ACE_exitcode *status = 0); 00260 00261 /** 00262 * Wait indefinitely for a single, specified process to terminate. 00263 * If @a pid is 0, waits for any of the managed processes (but see the 00264 * note concerning "sloppy process cleanup on unix"). 00265 * If @a pid != 0, this method waits for that process only. 00266 * 00267 * @retval The pid of the process which exited, or 00268 * ACE_INVALID_PID on error. 00269 */ 00270 pid_t wait (pid_t pid, 00271 ACE_exitcode *status = 0); 00272 00273 /** 00274 * @deprecated 00275 * Reap the result of a single process by calling ACE_OS::waitpid(), 00276 * therefore, this method is not portable to Windows. If the child is 00277 * successfully reaped, remove() is called automatically. 00278 * Use one of the wait() methods instead of this method. 00279 */ 00280 int reap (pid_t pid = -1, 00281 ACE_exitcode *stat_loc = 0, 00282 int options = WNOHANG); 00283 //@} 00284 00285 /** 00286 * @name Utility methods 00287 */ 00288 //@{ 00289 /** 00290 * Register an event handler to be called back when the specified 00291 * process exits. If @a pid == ACE_INVALID_PID this handler is called 00292 * when any process with no specific handler exits. 00293 * 00294 * @warning In multithreaded applications, there is a race condition 00295 * if a process exits between the time it is spawned and when its 00296 * handler is registered. To avoid this, register the handler at 00297 * the time the process is spawned. 00298 */ 00299 int register_handler (ACE_Event_Handler *event_handler, 00300 pid_t pid = ACE_INVALID_PID); 00301 00302 /** 00303 * Remove process @a pid from the ACE_Process_Manager's internal records. 00304 * This is called automatically by the reap() method after it successfully 00305 * reaps a process. It's also possible to call this method 00306 * directly from a signal handler, but don't call both reap() and 00307 * remove()! 00308 */ 00309 int remove (pid_t pid); 00310 00311 /// Return the number of managed processes. 00312 size_t managed (void) const; 00313 00314 /** 00315 * Sets the scheduling parameters for process identified by @a pid by 00316 * passing @a params, @a pid to ACE_OS::sched_params(). 00317 * 00318 * @retval 0 on success, -1 on failure, and ACE_INVALID_PID when the 00319 * specified @a pid is not managed by this ACE_Process_Manager. 00320 */ 00321 int set_scheduler (const ACE_Sched_Params ¶ms, pid_t pid); 00322 00323 /** 00324 * Sets the scheduling parameters for all the processes managed by 00325 * this ACE_Process_Manager by passing @a params to 00326 * ACE_OS::sched_params(). 00327 * 00328 * @retval 0 on success, -1 on failure. 00329 */ 00330 int set_scheduler_all (const ACE_Sched_Params ¶ms); 00331 00332 /// Dump the state of an object. 00333 void dump (void) const; 00334 00335 /// Declare the dynamic allocation hooks. 00336 ACE_ALLOC_HOOK_DECLARE; 00337 //@} 00338 00339 protected: 00340 // = These methods allow a <Process_Manager> to be an <Event_Handler>. 00341 00342 // As an <Event_Handler>, the <Process_Manager> automagically 00343 // detects child Processes exiting and calls notify_proc_handler() 00344 // and remove(). This means that you don't have to (shouldn't!) 00345 // call the wait(...) methods yourself. 00346 00347 // On Unix, we can't detect individual process termination very 00348 // well; the best method is to catch SIGCHLD and then call the 00349 // polling wait() function to collect any available exit statuses. 00350 // However, we don't want to do this from within a signal handler 00351 // because of the restrictions associated. Therefore (following the 00352 // lead in examples/mumble) we open a bogus handle (to ACE_DEV_NULL) 00353 // and register that handle with our Reactor. Then, when our 00354 // SIGCHLD handler gets invoked, we tell the Reactor that the bogus 00355 // handle is readable. That will cause the handle_input() function 00356 // to be called once we're out of the interrupt context, and 00357 // handle_input() collects exit statuses. 00358 00359 // On Win32, we simply register ourself with the Reactor to deal 00360 // with the Process handle becoming signaled. No muss, no fuss, no 00361 // signal handler, and no dummy handle. 00362 00363 #if !defined(ACE_WIN32) 00364 /// Collect one (or more, on unix) process exit status. 00365 virtual int handle_input (ACE_HANDLE proc); 00366 #endif // !defined(ACE_WIN32) 00367 00368 /** 00369 * On Unix, this routine is called asynchronously when a SIGCHLD is 00370 * received. We just tweak the reactor so that it'll call back our 00371 * <handle_input> function, which allows us to handle Process exits 00372 * synchronously. 00373 * 00374 * On Win32, this routine is called synchronously, and is passed the 00375 * HANDLE of the Process that exited, so we can do all our work here 00376 */ 00377 virtual int handle_signal (int signum, 00378 siginfo_t * = 0, 00379 ucontext_t * = 0); 00380 00381 private: 00382 00383 /** 00384 * @struct Process_Descriptor 00385 * 00386 * @internal This struct is for internal use only by ACE_Process_Manager. 00387 * 00388 * @brief Information describing each process that's controlled by an 00389 * ACE_Process_Manager. 00390 */ 00391 struct Process_Descriptor 00392 { 00393 /// Default ctor/dtor. 00394 Process_Descriptor (void); 00395 ~Process_Descriptor (void); 00396 00397 /// Describes the process itself. 00398 ACE_Process *process_; 00399 00400 /// Function to call when process exits 00401 ACE_Event_Handler *exit_notify_; 00402 00403 /// Dump the state of an object. 00404 void dump (void) const; 00405 }; 00406 00407 /// Resize the pool of Process_Descriptors. 00408 int resize (size_t); 00409 00410 /// Locate the index of the table slot occupied by @a process_id. 00411 /// Returns -1 if @a process_id is not in the @c process_table_ 00412 ssize_t find_proc (pid_t process_id); 00413 00414 #if defined (ACE_WIN32) 00415 /// Locate the index of the table slot occupied by @a process_handle. 00416 /// Returns ~0 if @a process_handle is not in the @c process_table_ 00417 ssize_t find_proc (ACE_HANDLE process_handle); 00418 #endif /* ACE_WIN32 */ 00419 00420 /// Insert a process in the table (checks for duplicates). Omitting 00421 /// the process handle won't work on Win32... 00422 /// Register @a event_handler to be called back when the process exits. 00423 int insert_proc (ACE_Process *process, 00424 ACE_Event_Handler *event_handler = 0); 00425 00426 /** 00427 * Append information about a process, i.e., its <process_id> in the 00428 * @c process_table_. Each entry is added at the end, growing the 00429 * table if necessary. 00430 * Register @a event_handler to be called back when the process exits. 00431 */ 00432 int append_proc (ACE_Process *process, 00433 ACE_Event_Handler *event_handler = 0); 00434 00435 /// Actually removes the process at index @a n from the table. This method 00436 /// must be called with locks held. 00437 int remove_proc (size_t n); 00438 00439 /// If there's a specific handler for the Process at index @a n in the 00440 /// table, or there's a default handler, call it. 00441 int notify_proc_handler (size_t n, ACE_exitcode status); 00442 00443 /// Vector that describes process state within the Process_Manager. 00444 Process_Descriptor *process_table_; 00445 00446 /// Maximum number of processes we can manage (should be dynamically 00447 /// allocated). 00448 size_t max_process_table_size_; 00449 00450 /// Current number of processes we are managing. 00451 size_t current_count_; 00452 00453 /// This event handler is used to notify when a process we control 00454 /// exits. 00455 ACE_Event_Handler *default_exit_handler_; 00456 00457 /// Singleton pointer. 00458 static ACE_Process_Manager *instance_; 00459 00460 /// Controls whether the <Process_Manager> is deleted when we shut 00461 /// down (we can only delete it safely if we created it!) 00462 static bool delete_instance_; 00463 00464 #if defined (ACE_HAS_THREADS) 00465 /// This lock protects access/ops on @c process_table_. 00466 ACE_Recursive_Thread_Mutex lock_; 00467 #endif /* ACE_HAS_THREADS */ 00468 }; 00469 00470 ACE_END_VERSIONED_NAMESPACE_DECL 00471 00472 #if defined (__ACE_INLINE__) 00473 #include "ace/Process_Manager.inl" 00474 #endif /* __ACE_INLINE__ */ 00475 00476 #include /**/ "ace/post.h" 00477 #endif /* ACE_PROCESS_MANAGER_H */