Process_Manager.h

Go to the documentation of this file.
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 &params, 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 &params);
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 */

Generated on Tue Feb 2 17:18:42 2010 for ACE by  doxygen 1.4.7