Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

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,v 1.1.1.4 2003/02/21 18:36:32 chad Exp $
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 #include "ace/pre.h"
00016 
00017 #include "ace/Synch.h"
00018 #include "ace/Reactor.h"
00019 #include "ace/Event_Handler.h"
00020 
00021 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00022 # pragma once
00023 #endif /* ACE_LACKS_PRAGMA_ONCE */
00024 
00025 #include "ace/Process.h"
00026 
00027 /**
00028  * @class ACE_Process_Descriptor
00029  *
00030  * @brief Information describing each process that's controlled by an
00031  * <ACE_Process_Manager>.
00032  */
00033 class ACE_Export ACE_Process_Descriptor
00034 {
00035 private:
00036   friend class ACE_Process_Manager;
00037 
00038   /// Default ctor/dtor.
00039   ACE_Process_Descriptor (void);
00040   ~ACE_Process_Descriptor (void);
00041 
00042   /// Describes the process itself.
00043   ACE_Process *process_;
00044 
00045   /// function to call when process exits
00046   ACE_Event_Handler *exit_notify_;
00047 
00048   /// Dump the state of an object.
00049   void dump (void) const;
00050 };
00051 
00052 /**
00053  * @class ACE_Process_Manager
00054  *
00055  * @brief Manages a group of processes.
00056  *
00057  * This class allows applications to control groups of processes,
00058  * similar to how the <ACE_Thread_Manager> controls groups of
00059  * threads.  Naturally, it doesn't work at all on platforms, such
00060  * as VxWorks or pSoS, that don't support process.
00061  * There are two (main) ways of using <ACE_Process_Manager>,
00062  * depending on how involved you wish to be with the termination
00063  * of managed <ACE_Process>es.  If you just want <Process>es to
00064  * go away when they're finished, simply register the
00065  * <Process_Manager> with an <ACE_Reactor>:
00066  * ACE_Process_Manager mgr( 100, some_reactor )
00067  * -or-
00068  * ACE_Process_Manager mgr;
00069  * ...
00070  * mgr.open( 100, some_reactor );
00071  * Then, the <Process_Manager> will clean up after any
00072  * <Process>es that it spawns.  (On Unix, this means executing a
00073  * wait(2) to collect the exit status -- and avoid zombie
00074  * processes; on Win32, it means closing the process and thread
00075  * HANDLEs that are created when CreateProcess is called.)
00076  * If, on the other hand (and for some inexplicable reason) you
00077  * want to explicitly invoke the terminated <Process> cleanup
00078  * code, then *don't* register the <Process_Manager> with a
00079  * Reactor, and be sure to call one of the
00080  * <Process_Manager::wait> functions whenever there might be
00081  * managed <Process>es that have exited.
00082  * Note that in either case, <Process_Manager> allows you to
00083  * register "<Event_Handlers>" to be called when a specific
00084  * <Process> exits, or when any <Process> without a specific
00085  * <Event_Handler> exits.  When a <Process> exits, the
00086  * appropriate <Event_Handler>'s <handle_input> is called; the
00087  * <ACE_HANDLE> passed is either the Process' HANDLE (on Win32),
00088  * or its pid cast to an <ACE_HANDLE> (on unix).
00089  * It is also possible to call the <Process_Manager::wait>
00090  * functions even though the <Process_Manager> is registered with
00091  * a <Reactor>.
00092  * Note also that the wait functions are "sloppy" on Unix,
00093  * because there's no good way to wait for a subset of the
00094  * children of a process.  The wait functions may end up
00095  * collecting the exit status of a process that's not managed by
00096  * the <Process_Manager> whose <wait> you invoked.  It's best to
00097  * only use a single <Process_Manager>, and to create all
00098  * subprocesses by calling that <Process_Manager>'s <spawn>
00099  * method.  
00100  * Incidentally, when you register your <Process_Manager> with a
00101  * <Reactor> its notification pipe is used to help "reap" the
00102  * available exit statuses.  Therefore, you must not use a
00103  * <Reactor> whose notify pipe has been disabled.  Here's the
00104  * sequence of steps used to reap the exit statuses in this case:
00105  * + The <Process_Manager> registers a signal handler for
00106  *   SIGCHLD.
00107  * + The SIGCHLD handler, when invoked, uses the <Reactor>'s
00108  *   <notify> method to inform the <Reactor> to wake up.
00109  * + Next, the <Reactor> calls the <Process_Manager>'s
00110  *   <handle_input>, this happens synchronously, not in
00111  *   sighandler-space.
00112  * + The <handle_input> method collects all available exit
00113  *   statuses.
00114  */
00115 class ACE_Export ACE_Process_Manager : protected ACE_Event_Handler
00116 {
00117 public:
00118   friend class ACE_Process_Control;
00119 
00120   enum
00121   {
00122     DEFAULT_SIZE = 100
00123   };
00124 
00125   // = Initialization and termination methods.
00126   /**
00127    * Initialize an <ACE_Process_Manager> with a table containing up to
00128    * <size> processes.  This table resizes itself automatically as
00129    * needed.  If a non-NULL <reactor> is provided, this
00130    * <ACE_Process_Manager> uses it to notify an application when a
00131    * process it controls exits.  By default, however, we don't use an
00132    * <ACE_Reactor>.
00133    */
00134   ACE_Process_Manager (size_t size = ACE_Process_Manager::DEFAULT_SIZE,
00135                        ACE_Reactor *reactor = 0);
00136 
00137   /**
00138    * Initialize an <ACE_Process_Manager> with a table containing up to
00139    * <size> processes.  This table resizes itself automatically as
00140    * needed.  If a non-NULL <reactor> is provided, this
00141    * <ACE_Process_Manager> uses it to notify an application when a
00142    * process it controls exits.  By default, however, we don't use an
00143    * <ACE_Reactor>.
00144    */
00145   int open (size_t size = DEFAULT_SIZE,
00146             ACE_Reactor *r = 0);
00147 
00148   /// Release all resources.  Do not wait for processes to exit.
00149   int close (void);
00150 
00151   /// Destructor releases all resources and does not wait for processes
00152   /// to exit.
00153   virtual ~ACE_Process_Manager (void);
00154 
00155   // = Singleton accessors.
00156   /// Get pointer to a process-wide <ACE_Process_Manager>.
00157   static ACE_Process_Manager *instance (void);
00158 
00159   /// Set pointer to a process-wide <ACE_Process_Manager> and return
00160   /// existing pointer.
00161   static ACE_Process_Manager *instance (ACE_Process_Manager *);
00162 
00163   /// Delete the dynamically allocated singleton.
00164   static void close_singleton (void);
00165 
00166   /// Cleanup method, used by the <ACE_Object_Manager> to destroy the
00167   /// singleton.
00168   static void cleanup (void *instance, void *arg);
00169 
00170   // = Process creation methods.
00171 
00172   /**
00173    * Create a new process by passing <options> to <proc.spawn>.  On
00174    * success, returns the process id of the child that was created.
00175    * On failure, returns ACE_INVALID_PID.
00176    */
00177   pid_t spawn (ACE_Process *proc,
00178                ACE_Process_Options &options);
00179 
00180   /**
00181    * Create a new process by passing <options> to
00182    * <ACE_Process::spawn>.  On success, returns the process id of the
00183    * child that was created.  On failure, returns ACE_INVALID_PID.
00184    */
00185   pid_t spawn (ACE_Process_Options &options);
00186 
00187   /**
00188    * Create <n> new processes by passing <options> to
00189    * <ACE_Process::spawn>, which is called <n> times.  If <child_pids>
00190    * is non-0 it is expected to be an array of <n> <pid_t>'s, which
00191    * are filled in with the process ids of each newly created process.
00192    * Returns 0 on success and -1 on failure.
00193    */
00194   int spawn_n (size_t n,
00195                ACE_Process_Options &options,
00196                pid_t *child_pids = 0);
00197 
00198   // = Process synchronization operations.
00199 
00200   /**
00201    * Block until there are no more child processes running that were
00202    * <spawn>ed by this <ACE_Process_Manager>.  Unlike the <wait> call
00203    * below, this method does not require a signal handler or
00204    * <ACE_OS::sigwait> because it simply blocks synchronously waiting
00205    * for all the children managed by this <ACE_Process_Manager> to
00206    * exit.  Note that this does not return any status information
00207    * about the success or failure of exiting child processes, although
00208    * any registered exit_handlers are called.  Returns 0 on success
00209    * (and <remove>s the corresponding <ACE_Process_Descriptor> entries
00210    * from the <Process_Manager>; otherwise, returns -1 on failure.
00211    */
00212   int wait (const ACE_Time_Value &timeout = ACE_Time_Value::max_time);
00213 
00214   /**
00215    * Wait up to <timeout> for a single process to terminate.  If
00216    * pid==0, waits for any of the managed <Process>es (but see the
00217    * note in the class documentation above for caveats about this --
00218    * "sloppy process cleanup on unix") If pid != 0, waits for that <Process>
00219    * only.  Returns the pid of the Process whose exit was handled, 0
00220    * if a timeout occurred, or ACE_INVALID_PID on error.
00221    */
00222   pid_t wait (pid_t pid,
00223               const ACE_Time_Value &timeout,
00224               ACE_exitcode *status = 0);
00225 
00226   /**
00227    * Wait indefinitely for a single process to terminate.  If pid==0,
00228    * waits for any of the managed <Process>es (but see the note in
00229    * the class documentation for caveats about this -- "sloppy Process
00230    * cleanup on unix") If pid != 0, waits for that <Process> only.
00231    * Returns the pid of the process whose exit was handled, or
00232    * ACE_INVALID_PID on error.
00233    */
00234   pid_t wait (pid_t pid,
00235               ACE_exitcode *status = 0);
00236 
00237   /**
00238    * Reap the result of a single process by calling <ACE_OS::waitpid>,
00239    * therefore, this method is not portable to Win32.  If the child is
00240    * successfully reaped, <remove> is called automatically.  This
00241    * method does the same thing that the <wait> method directly above
00242    * it does -- It's just here for backwards compatibility.
00243    */
00244   int reap (pid_t pid = -1,
00245             ACE_exitcode *stat_loc = 0,
00246             int options = WNOHANG);
00247 
00248   // = Utility methods.
00249   /**
00250    * Register an Event_Handler to be called back when the specified
00251    * process exits.  If pid == ACE_INVALID_PID this handler is called
00252    * when any process with no specific handler exits.
00253    */
00254   int register_handler (ACE_Event_Handler *event_handler,
00255                         pid_t pid = ACE_INVALID_PID);
00256 
00257   /**
00258    * Remove process <pid> from the table.  This is called
00259    * automatically by the <reap> method after it successfully reaped a
00260    * <SIGCHLD> signal.  It's also possible to call this method
00261    * directly from a signal handler, but don't call both <reap> and
00262    * <remove>!
00263    */
00264   int remove (pid_t pid);
00265 
00266   /**
00267    * Abruptly terminate a single process with id <pid> using the
00268    * <ACE::terminate_process> method.  Note that this call is
00269    * potentially dangerous to use since the process being terminated
00270    * may not have a chance to cleanup before it shuts down.  Returns 0
00271    * on success and -1 on failure.
00272    */
00273   int terminate (pid_t pid);
00274 
00275   /// On OSs that support signals, send the signal to the specified
00276   /// process.  Returns 0 on success and -1 on failure.
00277   int terminate (pid_t pid,
00278                  int sig);
00279 
00280   /// Return the number of managed Processes.
00281   size_t managed (void) const;
00282 
00283   /// Dump the state of an object.
00284   void dump (void) const;
00285 
00286   /// Declare the dynamic allocation hooks.
00287   ACE_ALLOC_HOOK_DECLARE;
00288 
00289 protected:
00290   // = These methods allow a <Process_Manager> to be an <Event_Handler>.
00291 
00292   // As an <Event_Handler>, the <Process_Manager> automagically
00293   // detects child Processes exiting and calls notify_proc_handler()
00294   // and remove().  This means that you don't have to (shouldn't!)
00295   // call the wait(...)  methods yourself.
00296 
00297   // On Unix, we can't detect individual process termination very
00298   // well; the best method is to catch SIGCHLD and then call the
00299   // polling wait() function to collect any available exit statuses.
00300   // However, we don't want to do this from within a signal handler
00301   // because of the restrictions associated.  Therefore (following the
00302   // lead in examples/mumble) we open a bogus handle (to ACE_DEV_NULL)
00303   // and register that handle with our Reactor.  Then, when our
00304   // SIGCHLD handler gets invoked, we tell the Reactor that the bogus
00305   // handle is readable.  That will cause the handle_input() function
00306   // to be called once we're out of the interrupt context, and
00307   // handle_input() collects exit statuses.
00308 
00309   // On Win32, we simply register ourself with the Reactor to deal
00310   // with the Process handle becoming signaled.  No muss, no fuss, no
00311   // signal handler, and no dummy handle.
00312 
00313 #if !defined(ACE_WIN32)
00314   /// Collect one (or more, on unix) process exit status.
00315   virtual int handle_input (ACE_HANDLE proc);
00316 #endif // !defined(ACE_WIN32)
00317 
00318   /**
00319    * On Unix, this routine is called asynchronously when a SIGCHLD is
00320    * received.  We just tweak the reactor so that it'll call back our
00321    * <handle_input> function, which allows us to handle Process exits
00322    * synchronously.
00323    *
00324    * On Win32, this routine is called synchronously, and is passed the
00325    * HANDLE of the Process that exited, so we can do all our work here
00326    */
00327   virtual int handle_signal (int signum,
00328                              siginfo_t * = 0,
00329                              ucontext_t * = 0);
00330 
00331 private:
00332   /// Resize the pool of Process_Descriptors.
00333   int resize (size_t);
00334 
00335   /// Locate the index of the table slot occupied by <process_id>.
00336   /// Returns -1 if <process_id> is not in the <process_table_>
00337   ssize_t find_proc (pid_t process_id);
00338 
00339 #if defined (ACE_WIN32)
00340   /// Locate the index of the table slot occupied by <process_handle>.
00341   /// Returns ~0 if <process_handle> is not in the <process_table_>
00342   ssize_t find_proc (ACE_HANDLE process_handle);
00343 #endif /* ACE_WIN32 */
00344 
00345   /// Insert a process in the table (checks for duplicates).  Omitting
00346   /// the process handle won't work on Win32...
00347   int insert_proc (ACE_Process *process);
00348 
00349   /**
00350    * Append information about a process, i.e., its <process_id> in the
00351    * <process_table_>.  Each entry is added at the end, growing the
00352    * table if necessary.
00353    */
00354   int append_proc (ACE_Process *process);
00355 
00356   /// Actually removes the process at index <n> from the table.  This method
00357   /// must be called with locks held.
00358   int remove_proc (size_t n);
00359 
00360   /// If there's a specific handler for the Process at index <n> in the
00361   /// table, or there's a default handler, call it.
00362   int notify_proc_handler (size_t n,
00363                            ACE_exitcode status);
00364 
00365   /// Vector that describes process state within the Process_Manager.
00366   ACE_Process_Descriptor *process_table_;
00367 
00368   /// Maximum number of processes we can manage (should be dynamically
00369   /// allocated).
00370   size_t max_process_table_size_;
00371 
00372   /// Current number of processes we are managing.
00373   size_t current_count_;
00374 
00375   /// This event handler is used to notify when a process we control
00376   /// exits.
00377   ACE_Event_Handler *default_exit_handler_;
00378 
00379   /// Singleton pointer.
00380   static ACE_Process_Manager *instance_;
00381 
00382   /// Controls whether the <Process_Manager> is deleted when we shut
00383   /// down (we can only delete it safely if we created it!)
00384   static int delete_instance_;
00385 
00386 #if defined (ACE_HAS_THREADS)
00387   /// This lock protects access/ops on <process_table_>.
00388   ACE_Recursive_Thread_Mutex lock_;
00389 #endif /* ACE_HAS_THREADS */
00390 };
00391 
00392 #if defined (__ACE_INLINE__)
00393 #include "ace/Process_Manager.i"
00394 #endif /* __ACE_INLINE__ */
00395 
00396 #include "ace/post.h"
00397 #endif /* ACE_PROCESS_MANAGER_H */

Generated on Mon Jun 16 11:20:55 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002