summaryrefslogtreecommitdiff
path: root/ace/Process_Manager.h
diff options
context:
space:
mode:
Diffstat (limited to 'ace/Process_Manager.h')
-rw-r--r--ace/Process_Manager.h388
1 files changed, 0 insertions, 388 deletions
diff --git a/ace/Process_Manager.h b/ace/Process_Manager.h
deleted file mode 100644
index 148b7f28e1d..00000000000
--- a/ace/Process_Manager.h
+++ /dev/null
@@ -1,388 +0,0 @@
-/* -*- C++ -*- */
-// $Id$
-
-// ============================================================================
-//
-// = LIBRARY
-// ace
-//
-// = FILENAME
-// Process_Manager.h
-//
-// = AUTHOR
-// Douglas C. Schmidt <schmidt@cs.wustl.edu>
-//
-// ============================================================================
-
-#ifndef ACE_PROCESS_MANAGER_H
-#define ACE_PROCESS_MANAGER_H
-
-#include "ace/Synch.h"
-#include "ace/Reactor.h"
-#include "ace/Event_Handler.h"
-
-#if !defined (ACE_LACKS_PRAGMA_ONCE)
-# pragma once
-#endif /* ACE_LACKS_PRAGMA_ONCE */
-
-#include "ace/Process.h"
-
-class ACE_Export ACE_Process_Descriptor
-{
- // = TITLE
- // Information describing each process that's controlled by an
- // <ACE_Process_Manager>.
-private:
- friend class ACE_Process_Manager;
-
- ACE_Process_Descriptor (void);
- ~ACE_Process_Descriptor (void);
- // Default ctor/dtor.
-
- ACE_Process *process_;
- // Describes the process itself.
-
- ACE_Event_Handler *exit_notify_;
- // function to call when process exits
-
- void dump (void) const;
- // Dump the state of an object.
-};
-
-class ACE_Export ACE_Process_Manager : protected ACE_Event_Handler
-{
- // = TITLE
- // Manages a group of processes.
- //
- // = DESCRIPTION
- // 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 <ACE_Process>es. If you just want <Process>es to
- // go away when they're finished, simply register the
- // <Process_Manager> with an <ACE_Reactor>:
- //
- // ACE_Process_Manager mgr( 100, some_reactor )
- // -or-
- // ACE_Process_Manager mgr;
- // ...
- // mgr.open( 100, some_reactor );
- //
- // Then, the <Process_Manager> will clean up after any
- // <Process>es 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.)
- //
- // If, on the other hand (and for some inexplicable reason) you
- // want to explicitly invoke the terminated <Process> cleanup
- // code, then *don't* register the <Process_Manager> with a
- // Reactor, and be sure to call one of the
- // <Process_Manager::wait> functions whenever there might be
- // managed <Process>es that have exited.
- //
- // Note that in either case, <Process_Manager> allows you to
- // register "<Event_Handlers>" to be called when a specific
- // <Process> exits, or when any <Process> without a specific
- // <Event_Handler> exits. When a <Process> exits, the
- // appropriate <Event_Handler>'s <handle_input> is called; the
- // <ACE_HANDLE> passed is either the Process' HANDLE (on Win32),
- // or its pid cast to an <ACE_HANDLE> (on unix).
- //
- // It is also possible to call the <Process_Manager::wait>
- // functions even though the <Process_Manager> is registered with
- // a <Reactor>. I don't know what happens in this case, but it's
- // probably not *too* bad.
- //
- // Note also 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 <Process_Manager> whose <wait> you invoked. It's best to
- // only use a single <Process_Manager>, and to create all
- // subprocesses by calling that <Process_Manager>'s <spawn>
- // method. (I have some ideas for workarounds to improve this
- // situation, but I consider it fairly low priority because I
- // think the "single <Process_Manager>" pattern will be
- // sufficient in most cases.)
- //
- // Incidentally, here's how the auto-reaping works on unix when
- // you register your <Process_Manager> with a <Reactor>:
- //
- // * the <Process_Manager> opens ACE_DEV_NULL to get a dummy
- // <HANDLE>.
- //
- // * the dummy <HANDLE> is registered with the <Reactor>, but
- // with a NULL_MASK so that it's never normally active.
- //
- // * the <Process_Manager> also registers a signal handler for
- // SIGCHLD.
- //
- // * the SIGCHLD handler, when invoked, marks the dummy <HANDLE>
- // as ready for input.
- //
- // * the <Reactor> calls the <Process_Manager>'s <handle_input>
- // (this happens synchronously, not in sighandler-space).
- //
- // * <handle_input> collects all available exit statuses.
-public:
- friend class ACE_Process_Control;
-
- enum
- {
- DEFAULT_SIZE = 100
- };
-
- // = Initialization and termination methods.
- 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
- // <size> processes. This table resizes itself automatically as
- // needed. If a non-NULL <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 = DEFAULT_SIZE,
- ACE_Reactor *r = 0);
- // Initialize an <ACE_Process_Manager> with a table containing up to
- // <size> processes. This table resizes itself automatically as
- // needed. If a non-NULL <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 close (void);
- // Release all resources. Do not wait for processes to exit.
-
- virtual ~ACE_Process_Manager (void);
- // Destructor releases all resources and does not wait for processes
- // to exit.
-
- // = Singleton accessors.
- static ACE_Process_Manager *instance (void);
- // Get pointer to a process-wide <ACE_Process_Manager>.
-
- static ACE_Process_Manager *instance (ACE_Process_Manager *);
- // Set pointer to a process-wide <ACE_Process_Manager> and return
- // existing pointer.
-
- // = Process creation methods.
-
- pid_t spawn (ACE_Process *proc,
- ACE_Process_Options &options);
- // Create a new process by passing <options> to <proc.spawn>. 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);
- // Create a new process by passing <options> to
- // <ACE_Process::spawn>. On success, returns the process id of the
- // child that was created. On failure, returns ACE_INVALID_PID.
-
- int spawn_n (size_t n,
- ACE_Process_Options &options,
- pid_t *child_pids = 0);
- // Create <n> new processes by passing <options> to
- // <ACE_Process::spawn>, which is called <n> times. If <child_pids>
- // is non-0 it is expected to be an array of <n> <pid_t>'s, which
- // are filled in with the process ids of each newly created process.
- // Returns 0 on success and -1 on failure.
-
- // = Process synchronization operations.
-
- int wait (const ACE_Time_Value &timeout = ACE_Time_Value::max_time);
- // Block until there are no more child processes running that were
- // <spawn>ed by this <ACE_Process_Manager>. Unlike the <wait> call
- // below, this method does not require a signal handler or
- // <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. Returns 0 on success
- // (and <remove>s the corresponding <ACE_Process_Descriptor> entries
- // from the <Process_Manager>; otherwise, returns -1 on failure.
-
- pid_t wait (pid_t pid,
- const ACE_Time_Value &timeout,
- ACE_exitcode *status = 0);
- // Wait up to <timeout> for a single process to terminate. If
- // pid==0, waits for any of the managed <Process>es (but see the
- // note in DESCRIPTION above for caveats about this -- "sloppy
- // Process cleanup on unix") If pid != 0, waits for that <Process>
- // only. Returns the pid of the Process whose exit was handled, 0
- // if a timeout occurred, or ACE_INVALID_PID on error.
-
- pid_t wait (pid_t pid,
- ACE_exitcode *status = 0);
- // Wait indefinitely for a single process to terminate. If pid==0,
- // waits for any of the managed <Process>es (but see the note in
- // DESCRIPTION above for caveats about this -- "sloppy Process
- // cleanup on unix") If pid != 0, waits for that <Process> only.
- // Returns the pid of the process whose exit was handled, or
- // ACE_INVALID_PID on error.
-
- int reap (pid_t pid = -1,
- ACE_exitcode *stat_loc = 0,
- int options = WNOHANG);
- // Reap the result of a single process by calling <ACE_OS::waitpid>,
- // therefore, this method is not portable to Win32. If the child is
- // successfully reaped, <remove> is called automatically. This
- // method does the same thing that the <wait> method directly above
- // it does -- It's just here for backwards compatibility.
-
- // = Utility methods.
- int register_handler (ACE_Event_Handler *event_handler,
- pid_t pid = ACE_INVALID_PID);
- // Register an Event_Handler to be called back when the specified
- // process exits. If pid == ACE_INVALID_PID this handler is called
- // when any process with no specific handler exits.
-
- int remove (pid_t pid);
- // Remove process <pid> from the table. This is called
- // automatically by the <reap> method after it successfully reaped a
- // <SIGCHLD> signal. It's also possible to call this method
- // directly from a signal handler, but don't call both <reap> and
- // <remove>!
-
- int terminate (pid_t pid);
- // Abruptly terminate a single process with id <pid> using the
- // <ACE::terminate_process> method. Note that this call is
- // potentially dangerous to use since the process being terminated
- // may not have a chance to cleanup before it shuts down. Returns 0
- // on success and -1 on failure.
-
- int terminate (pid_t pid,
- int sig);
- // On OSs that support signals, send the signal to the specified
- // process. Returns 0 on success and -1 on failure.
-
- size_t managed (void) const;
- // Return the number of managed Processes.
-
- void dump (void) const;
- // Dump the state of an object.
-
- ACE_ALLOC_HOOK_DECLARE;
- // Declare the dynamic allocation hooks.
-
-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)
- virtual int handle_input (ACE_HANDLE proc);
- // Collect one (or more, on unix) Process exit status
-
- virtual ACE_HANDLE get_handle (void) const;
- // (unix only) : return dummy handle
-#endif // !defined(ACE_WIN32)
-
- virtual int handle_signal (int signum,
- siginfo_t * = 0,
- ucontext_t * = 0);
- // 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_close (ACE_HANDLE handle,
- ACE_Reactor_Mask close_mask);
- // we're being removed from Reactor...on unix, close bogus handle.
-
-private:
- int resize (size_t);
- // Resize the pool of Process_Descriptors.
-
- ssize_t find_proc (pid_t process_id);
- // Locate the index of the table slot occupied by <process_id>.
- // Returns -1 if <process_id> is not in the <process_table_>
-
-#if defined (ACE_WIN32)
- ssize_t find_proc (ACE_HANDLE process_handle);
- // Locate the index of the table slot occupied by <process_handle>.
- // Returns ~0 if <process_handle> is not in the <process_table_>
-#endif /* ACE_WIN32 */
-
- int insert_proc (ACE_Process *process);
- // Insert a process in the table (checks for duplicates). Omitting
- // the process handle won't work on Win32...
-
- int append_proc (ACE_Process *process);
- // 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.
-
- int remove_proc (size_t n);
- // Actually removes the process at index <n> from the table. This method
- // must be called with locks held.
-
- int notify_proc_handler (size_t n,
- ACE_exitcode status);
- // If there's a specific handler for the Process at index <n> in the
- // table, or there's a default handler, call it.
-
- ACE_Process_Descriptor *process_table_;
- // Vector that describes process state within the Process_Manager.
-
- size_t max_process_table_size_;
- // Maximum number of processes we can manage (should be dynamically
- // allocated).
-
- size_t current_count_;
- // Current number of processes we are managing.
-
-#if !defined(ACE_WIN32)
- ACE_HANDLE dummy_handle_;
- // Allows SIGCHLD to be handled synchronously.
-#endif
-
- ACE_Event_Handler *default_exit_handler_;
- // This event handler is used to notify when a process we control
- // exits.
-
- static ACE_Process_Manager *instance_;
- // Singleton pointer.
-
- static int delete_instance_;
- // Controls whether the <Process_Manager> is deleted when we shut
- // down (we can only delete it safely if we created it!)
-
-#if defined (ACE_HAS_THREADS)
- // = ACE_Thread_Mutex for access/ops on process_table_
- ACE_Thread_Mutex lock_;
-#endif /* ACE_HAS_THREADS */
-};
-
-#if defined (__ACE_INLINE__)
-#include "ace/Process_Manager.i"
-#endif /* __ACE_INLINE__ */
-
-#endif /* ACE_PROCESS_MANAGER_H */