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 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 &params,
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 */

Generated on Sun Jan 27 12:05:35 2008 for ACE by doxygen 1.3.6