diff options
Diffstat (limited to 'ACE/ace/Process_Manager.h')
-rw-r--r-- | ACE/ace/Process_Manager.h | 478 |
1 files changed, 0 insertions, 478 deletions
diff --git a/ACE/ace/Process_Manager.h b/ACE/ace/Process_Manager.h deleted file mode 100644 index cd9e2009eca..00000000000 --- a/ACE/ace/Process_Manager.h +++ /dev/null @@ -1,478 +0,0 @@ -// -*- C++ -*- - -//============================================================================= -/** - * @file Process_Manager.h - * - * $Id$ - * - * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> - */ -//============================================================================= - -#ifndef ACE_PROCESS_MANAGER_H -#define ACE_PROCESS_MANAGER_H - -#include /**/ "ace/pre.h" - -#include /**/ "ace/ACE_export.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/Process.h" -#include "ace/Event_Handler.h" -#include "ace/Time_Value.h" - -#if defined (ACE_HAS_THREADS) -# include "ace/Recursive_Thread_Mutex.h" -#endif /* ACE_HAS_THREADS */ - -ACE_BEGIN_VERSIONED_NAMESPACE_DECL - -class ACE_Reactor; - -/** - * @class ACE_Process_Manager - * - * @brief Manages a group of processes. - * - * This class allows applications to control groups of processes, - * similar to how the ACE_Thread_Manager controls groups of - * threads. Naturally, it doesn't work at all on platforms, such - * as VxWorks or pSoS, that don't support process. - * There are two main ways of using ACE_Process_Manager, - * depending on how involved you wish to be with the termination - * of managed processes. If you want processes to simply - * go away when they're finished, register the ACE_Process_Manager with - * an ACE_Reactor that can handle notifications of child process exit: - * @code - * ACE_Process_Manager mgr; - * // ... - * mgr.open (100, ACE_Reactor::instance ()); - * @endcode - * In this usage scenario, the ACE_Process_Manager will clean up after any - * processes that it spawns. (On Unix, this means executing a - * wait(2) to collect the exit status and avoid zombie - * processes; on Win32, it means closing the process and thread - * HANDLEs that are created when CreateProcess is called.) - * - * @note When you register a ACE_Process_Manager with a - * ACE_Reactor, the reactor's notification pipe is used to help reap the - * available process exit statuses. Therefore, you must not use a - * reactor whose notify pipe has been disabled. Here's the - * sequence of steps used to reap the exit statuses in this case: - * -# The ACE_Process_Manager registers a signal handler for - * SIGCHLD. - * -# The SIGCHLD handler, when invoked, uses the ACE_Reactor's - * notify() method to inform the ACE_Reactor to wake up. - * -# The ACE_Reactor calls the ACE_Process_Manager's - * handle_input() method; this happens synchronously, not in - * signal context. - * -# The handle_input() method collects all available exit - * statuses. - * - * If, on the other hand you want to wait "in line" to handle the - * terminated process cleanup code, call one of the wait functions - * whenever there might be managed processes that have exited. - * - * Note that in either case, ACE_Process_Manager allows you to - * register an ACE_Event_Handler to be called when a specific - * spawned process exits, or when any process without a specific - * ACE_Event_Handler exits. When a process exits, the - * appropriate ACE_Event_Handler's handle_input() method is called; the - * ACE_HANDLE passed is either the process's HANDLE (on Win32), - * or its pid cast to an ACE_HANDLE (on POSIX). - * It is also possible to call the wait() functions even when the - * ACE_Process_Manager is registered with a reactor. - * - * @note Be aware that the wait functions are "sloppy" on Unix, - * because there's no good way to wait for a subset of the - * children of a process. The wait functions may end up - * collecting the exit status of a process that's not managed by - * the ACE_Process_Manager whose wait() you invoked. It's best to - * only use a single ACE_Process_Manager, and to create all - * subprocesses by calling that manager's spawn() method. - */ -class ACE_Export ACE_Process_Manager : protected ACE_Event_Handler -{ -public: - friend class ACE_Process_Control; - - enum - { - DEFAULT_SIZE = 100 - }; - - /** - * @name Initialization and termination methods - */ - //@{ - /** - * Initialize an ACE_Process_Manager with a table containing up to - * @a size processes. This table resizes itself automatically as - * needed. If a @a reactor is provided, this - * ACE_Process_Manager uses it to notify an application when a - * process it controls exits. By default, however, we don't use an - * ACE_Reactor. - */ - ACE_Process_Manager (size_t size = ACE_Process_Manager::DEFAULT_SIZE, - ACE_Reactor *reactor = 0); - - /** - * Initialize an ACE_Process_Manager with a table containing up to - * @a size processes. This table resizes itself automatically as - * needed. If a @a reactor is provided, this - * ACE_Process_Manager uses it to notify an application when a - * process it controls exits. By default, however, we don't use an - * ACE_Reactor. - */ - int open (size_t size = ACE_Process_Manager::DEFAULT_SIZE, - ACE_Reactor *r = 0); - - /// Release all resources. Do not wait for processes to exit. - int close (void); - - /// Destructor releases all resources and does not wait for processes - /// to exit. - virtual ~ACE_Process_Manager (void); - - //@} - - /** - * @name Singleton access and control - */ - //@{ - /// Get pointer to a process-wide ACE_Process_Manager. - static ACE_Process_Manager *instance (void); - - /// Set pointer to a process-wide ACE_Process_Manager and return - /// existing pointer. - static ACE_Process_Manager *instance (ACE_Process_Manager *); - - /// Delete the dynamically allocated singleton. - static void close_singleton (void); - - /// Cleanup method, used by the ACE_Object_Manager to destroy the - /// singleton. - static void cleanup (void *instance, void *arg); - - //@} - - /** - * @name Process creation methods - */ - //@{ - /** - * Create a new process with specified @a options. - * Register @a event_handler to be called back when the process exits. - * - * On success, returns the process id of the child that was created. - * On failure, returns ACE_INVALID_PID. - */ - pid_t spawn (ACE_Process *proc, - ACE_Process_Options &options, - ACE_Event_Handler *event_handler = 0); - - /** - * Create a new process with the specified @a options. - * Register @a event_handler to be called back when the process exits. - * - * On success, returns the process id of the child that was created. - * On failure, returns ACE_INVALID_PID. - */ - pid_t spawn (ACE_Process_Options &options, - ACE_Event_Handler *event_handler = 0); - - /** - * Create @a n new processes with the same @a options. - * If @a child_pids is non-0 it is expected to be an array of at least - * @a n pid_t, which are filled in with the process IDs of the spawned - * processes. - * Register @a event_handler to be called back when each process exits. - * Returns 0 on success and -1 on failure. - */ - int spawn_n (size_t n, - ACE_Process_Options &options, - pid_t *child_pids = 0, - ACE_Event_Handler *event_Handler = 0); - //@} - - /** - * @name Process synchronization operations - */ - //@{ - /** - * Abruptly terminate a single process with id @a pid using the - * ACE::terminate_process() method which works on both signal-capable - * systems and on Windows. - * - * @note This call is potentially dangerous to use since the process - * being terminated may not have a chance to cleanup before it shuts down. - * - * @retval 0 on success and -1 on failure. - */ - int terminate (pid_t pid); - - /** - * Sends the specified signal to the specified process. - * - * @note This only works on platforms that have signal capability. In - * particular, it doesn't work on Windows. - * - * @retval 0 on success and -1 on failure. - */ - int terminate (pid_t pid, int sig); - - /** - * Block until there are no more child processes running that were - * spawned by this ACE_Process_Manager. Unlike the wait() method - * below, this method does not require a signal handler or use of - * ACE_OS::sigwait() because it simply blocks synchronously waiting - * for all the children managed by this ACE_Process_Manager to - * exit. Note that this does not return any status information - * about the success or failure of exiting child processes, although - * any registered exit handlers are called. - * - * @param timeout Relative time to wait for processes to terminate. - * - * @retval 0 on success; -1 on failure. - */ - int wait (const ACE_Time_Value &timeout = ACE_Time_Value::max_time); - - /** - * Wait up to @a timeout for a single specified process to terminate. - * If @a pid is 0, this method waits for any of the managed processes - * (but see the note concerning "sloppy process cleanup on unix"). - * If @a pid != 0, waits for that process only. - * - * @param pid Process ID - * @param timeout Relative time to wait for process to terminate - * @param status Exit status of terminated process - * - * @retval The pid of the process which exited, 0 - * if a timeout occurred, or ACE_INVALID_PID on error. - */ - pid_t wait (pid_t pid, - const ACE_Time_Value &timeout, - ACE_exitcode *status = 0); - - /** - * Wait indefinitely for a single, specified process to terminate. - * If @a pid is 0, waits for any of the managed processes (but see the - * note concerning "sloppy process cleanup on unix"). - * If @a pid != 0, this method waits for that process only. - * - * @retval The pid of the process which exited, or - * ACE_INVALID_PID on error. - */ - pid_t wait (pid_t pid, - ACE_exitcode *status = 0); - - /** - * @deprecated - * Reap the result of a single process by calling ACE_OS::waitpid(), - * therefore, this method is not portable to Windows. If the child is - * successfully reaped, remove() is called automatically. - * Use one of the wait() methods instead of this method. - */ - int reap (pid_t pid = -1, - ACE_exitcode *stat_loc = 0, - int options = WNOHANG); - //@} - - /** - * @name Utility methods - */ - //@{ - /** - * Register an event handler to be called back when the specified - * process exits. If @a pid == ACE_INVALID_PID this handler is called - * when any process with no specific handler exits. - * - * @warning In multithreaded applications, there is a race condition - * if a process exits between the time it is spawned and when its - * handler is registered. To avoid this, register the handler at - * the time the process is spawned. - */ - int register_handler (ACE_Event_Handler *event_handler, - pid_t pid = ACE_INVALID_PID); - - /** - * Remove process @a pid from the ACE_Process_Manager's internal records. - * This is called automatically by the reap() method after it successfully - * reaps a process. It's also possible to call this method - * directly from a signal handler, but don't call both reap() and - * remove()! - */ - int remove (pid_t pid); - - /// Return the number of managed processes. - size_t managed (void) const; - - /** - * Sets the scheduling parameters for process identified by @a pid by - * passing @a params, @a pid to ACE_OS::sched_params(). - * - * @retval 0 on success, -1 on failure, and ACE_INVALID_PID when the - * specified @a pid is not managed by this ACE_Process_Manager. - */ - int set_scheduler (const ACE_Sched_Params ¶ms, - pid_t pid); - - /** - * Sets the scheduling parameters for all the processes managed by - * this ACE_Process_Manager by passing @a params to - * ACE_OS::sched_params(). - * - * @retval 0 on success, -1 on failure. - */ - int set_scheduler_all (const ACE_Sched_Params &); - - /// Dump the state of an object. - void dump (void) const; - - /// Declare the dynamic allocation hooks. - ACE_ALLOC_HOOK_DECLARE; - //@} - -protected: - // = These methods allow a <Process_Manager> to be an <Event_Handler>. - - // As an <Event_Handler>, the <Process_Manager> automagically - // detects child Processes exiting and calls notify_proc_handler() - // and remove(). This means that you don't have to (shouldn't!) - // call the wait(...) methods yourself. - - // On Unix, we can't detect individual process termination very - // well; the best method is to catch SIGCHLD and then call the - // polling wait() function to collect any available exit statuses. - // However, we don't want to do this from within a signal handler - // because of the restrictions associated. Therefore (following the - // lead in examples/mumble) we open a bogus handle (to ACE_DEV_NULL) - // and register that handle with our Reactor. Then, when our - // SIGCHLD handler gets invoked, we tell the Reactor that the bogus - // handle is readable. That will cause the handle_input() function - // to be called once we're out of the interrupt context, and - // handle_input() collects exit statuses. - - // On Win32, we simply register ourself with the Reactor to deal - // with the Process handle becoming signaled. No muss, no fuss, no - // signal handler, and no dummy handle. - -#if !defined(ACE_WIN32) - /// Collect one (or more, on unix) process exit status. - virtual int handle_input (ACE_HANDLE proc); -#endif // !defined(ACE_WIN32) - - /** - * On Unix, this routine is called asynchronously when a SIGCHLD is - * received. We just tweak the reactor so that it'll call back our - * <handle_input> function, which allows us to handle Process exits - * synchronously. - * - * On Win32, this routine is called synchronously, and is passed the - * HANDLE of the Process that exited, so we can do all our work here - */ - virtual int handle_signal (int signum, - siginfo_t * = 0, - ucontext_t * = 0); - -private: - - /** - * @struct Process_Descriptor - * - * @internal This struct is for internal use only by ACE_Process_Manager. - * - * @brief Information describing each process that's controlled by an - * ACE_Process_Manager. - */ - struct Process_Descriptor - { - /// Default ctor/dtor. - Process_Descriptor (void); - ~Process_Descriptor (void); - - /// Describes the process itself. - ACE_Process *process_; - - /// function to call when process exits - ACE_Event_Handler *exit_notify_; - - /// Dump the state of an object. - void dump (void) const; - }; - - /// Resize the pool of Process_Descriptors. - int resize (size_t); - - /// Locate the index of the table slot occupied by @a process_id. - /// Returns -1 if @a process_id is not in the <process_table_> - ssize_t find_proc (pid_t process_id); - -#if defined (ACE_WIN32) - /// Locate the index of the table slot occupied by @a process_handle. - /// Returns ~0 if @a process_handle is not in the <process_table_> - ssize_t find_proc (ACE_HANDLE process_handle); -#endif /* ACE_WIN32 */ - - /// Insert a process in the table (checks for duplicates). Omitting - /// the process handle won't work on Win32... - /// Register @a event_handler to be called back when the process exits. - int insert_proc (ACE_Process *process, - ACE_Event_Handler *event_handler = 0); - - /** - * Append information about a process, i.e., its <process_id> in the - * <process_table_>. Each entry is added at the end, growing the - * table if necessary. - * Register @a event_handler to be called back when the process exits. - */ - int append_proc (ACE_Process *process, - ACE_Event_Handler *event_handler = 0); - - /// Actually removes the process at index @a n from the table. This method - /// must be called with locks held. - int remove_proc (size_t n); - - /// If there's a specific handler for the Process at index @a n in the - /// table, or there's a default handler, call it. - int notify_proc_handler (size_t n, ACE_exitcode status); - - /// Vector that describes process state within the Process_Manager. - Process_Descriptor *process_table_; - - /// Maximum number of processes we can manage (should be dynamically - /// allocated). - size_t max_process_table_size_; - - /// Current number of processes we are managing. - size_t current_count_; - - /// This event handler is used to notify when a process we control - /// exits. - ACE_Event_Handler *default_exit_handler_; - - /// Singleton pointer. - static ACE_Process_Manager *instance_; - - /// Controls whether the <Process_Manager> is deleted when we shut - /// down (we can only delete it safely if we created it!) - static bool delete_instance_; - -#if defined (ACE_HAS_THREADS) - /// This lock protects access/ops on <process_table_>. - ACE_Recursive_Thread_Mutex lock_; -#endif /* ACE_HAS_THREADS */ -}; - -ACE_END_VERSIONED_NAMESPACE_DECL - -#if defined (__ACE_INLINE__) -#include "ace/Process_Manager.inl" -#endif /* __ACE_INLINE__ */ - -#include /**/ "ace/post.h" -#endif /* ACE_PROCESS_MANAGER_H */ |