Process_Manager.h

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

Generated on Thu Nov 9 09:42:00 2006 for ACE by doxygen 1.3.6