ACE_Process_Manager Class Reference

Manages a group of processes. More...

#include <Process_Manager.h>

Inheritance diagram for ACE_Process_Manager:

Inheritance graph
[legend]
Collaboration diagram for ACE_Process_Manager:

Collaboration graph
[legend]
List of all members.

Public Types

 DEFAULT_SIZE = 100
enum  { DEFAULT_SIZE = 100 }

Public Member Functions

 ACE_Process_Manager (size_t size=ACE_Process_Manager::DEFAULT_SIZE, ACE_Reactor *reactor=0)
int open (size_t size=DEFAULT_SIZE, ACE_Reactor *r=0)
int close (void)
 Release all resources. Do not wait for processes to exit.
virtual ~ACE_Process_Manager (void)
pid_t spawn (ACE_Process *proc, ACE_Process_Options &options, ACE_Event_Handler *event_handler=0)
pid_t spawn (ACE_Process_Options &options, ACE_Event_Handler *event_handler=0)
int spawn_n (size_t n, ACE_Process_Options &options, pid_t *child_pids=0, ACE_Event_Handler *event_Handler=0)
int wait (const ACE_Time_Value &timeout=ACE_Time_Value::max_time)
pid_t wait (pid_t pid, const ACE_Time_Value &timeout, ACE_exitcode *status=0)
pid_t wait (pid_t pid, ACE_exitcode *status=0)
int reap (pid_t pid=-1, ACE_exitcode *stat_loc=0, int options=WNOHANG)
int register_handler (ACE_Event_Handler *event_handler, pid_t pid=ACE_INVALID_PID)
int remove (pid_t pid)
int terminate (pid_t pid)
int terminate (pid_t pid, int sig)
size_t managed (void) const
 Return the number of managed Processes.
int set_scheduler (const ACE_Sched_Params &params, pid_t pid)
int set_scheduler_all (const ACE_Sched_Params &)
void dump (void) const
 Dump the state of an object.

Static Public Member Functions

static ACE_Process_Managerinstance (void)
 Get pointer to a process-wide <ACE_Process_Manager>.
static ACE_Process_Managerinstance (ACE_Process_Manager *)
static void close_singleton (void)
 Delete the dynamically allocated singleton.
static void cleanup (void *instance, void *arg)

Public Attributes

 ACE_ALLOC_HOOK_DECLARE
 Declare the dynamic allocation hooks.

Protected Member Functions

virtual int handle_signal (int signum, siginfo_t *=0, ucontext_t *=0)

Private Member Functions

int resize (size_t)
 Resize the pool of Process_Descriptors.
ssize_t find_proc (pid_t process_id)
ssize_t find_proc (ACE_HANDLE process_handle)
int insert_proc (ACE_Process *process, ACE_Event_Handler *event_handler=0)
int append_proc (ACE_Process *process, ACE_Event_Handler *event_handler=0)
int remove_proc (size_t n)
int notify_proc_handler (size_t n, ACE_exitcode status)

Private Attributes

ACE_Process_Descriptorprocess_table_
 Vector that describes process state within the Process_Manager.
size_t max_process_table_size_
size_t current_count_
 Current number of processes we are managing.
ACE_Event_Handlerdefault_exit_handler_
ACE_Recursive_Thread_Mutex lock_
 This lock protects access/ops on <process_table_>.

Static Private Attributes

static ACE_Process_Managerinstance_ = 0
 Singleton pointer.
static int delete_instance_ = 0

Friends

class ACE_Process_Control

Detailed Description

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 <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>. 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. Incidentally, when you register your <Process_Manager> with a <Reactor> its notification pipe is used to help "reap" the available 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 <Process_Manager> registers a signal handler for SIGCHLD. + The SIGCHLD handler, when invoked, uses the <Reactor>'s <notify> method to inform the <Reactor> to wake up. + Next, the <Reactor> calls the <Process_Manager>'s <handle_input>, this happens synchronously, not in sighandler-space. + The <handle_input> method collects all available exit statuses.


Member Enumeration Documentation

anonymous enum

Enumerator:
DEFAULT_SIZE 


Constructor & Destructor Documentation

ACE_Process_Manager::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.

ACE_Process_Manager::~ACE_Process_Manager ( void   )  [virtual]

Destructor releases all resources and does not wait for processes to exit.


Member Function Documentation

int ACE_Process_Manager::append_proc ( ACE_Process process,
ACE_Event_Handler event_handler = 0 
) [private]

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 <event_handler> to be called back when the process exits.

ACE_BEGIN_VERSIONED_NAMESPACE_DECL void ACE_Process_Manager::cleanup ( void *  instance,
void *  arg 
) [static]

Cleanup method, used by the <ACE_Object_Manager> to destroy the singleton.

int ACE_Process_Manager::close ( void   ) 

Release all resources. Do not wait for processes to exit.

void ACE_Process_Manager::close_singleton ( void   )  [static]

Delete the dynamically allocated singleton.

void ACE_Process_Manager::dump ( void   )  const

Dump the state of an object.

ssize_t ACE_Process_Manager::find_proc ( ACE_HANDLE  process_handle  )  [private]

Locate the index of the table slot occupied by <process_handle>. Returns ~0 if <process_handle> is not in the <process_table_>

ssize_t ACE_Process_Manager::find_proc ( pid_t  process_id  )  [private]

Locate the index of the table slot occupied by <process_id>. Returns -1 if <process_id> is not in the <process_table_>

int ACE_Process_Manager::handle_signal ( int  signum,
siginfo_t = 0,
ucontext_t = 0 
) [protected, virtual]

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

Reimplemented from ACE_Event_Handler.

int ACE_Process_Manager::insert_proc ( ACE_Process process,
ACE_Event_Handler event_handler = 0 
) [private]

Insert a process in the table (checks for duplicates). Omitting the process handle won't work on Win32... Register <event_handler> to be called back when the process exits.

ACE_Process_Manager * ACE_Process_Manager::instance ( ACE_Process_Manager  )  [static]

Set pointer to a process-wide <ACE_Process_Manager> and return existing pointer.

ACE_Process_Manager * ACE_Process_Manager::instance ( void   )  [static]

Get pointer to a process-wide <ACE_Process_Manager>.

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE size_t ACE_Process_Manager::managed ( void   )  const

Return the number of managed Processes.

int ACE_Process_Manager::notify_proc_handler ( size_t  n,
ACE_exitcode  status 
) [private]

If there's a specific handler for the Process at index <n> in the table, or there's a default handler, call it.

int ACE_Process_Manager::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 ACE_Process_Manager::reap ( pid_t  pid = -1,
ACE_exitcode stat_loc = 0,
int  options = WNOHANG 
)

Deprecated:
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.

int ACE_Process_Manager::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.

Note:
In multi-threaded 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 ACE_Process_Manager::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 ACE_Process_Manager::remove_proc ( size_t  n  )  [private]

Actually removes the process at index <n> from the table. This method must be called with locks held.

int ACE_Process_Manager::resize ( size_t   )  [private]

Resize the pool of Process_Descriptors.

int ACE_Process_Manager::set_scheduler ( const ACE_Sched_Params params,
pid_t  pid 
)

Sets the scheduling parameters for the <Process> managed by <ACE_Process_Manager> identified by pid by passing <params>, <pid> to <ACE_OS::sched_params>. Returns 0 on success, -1 on failure, and ACE_INVALID_PID when given pid is not managed by <ACE_Process_Manager>.

int ACE_Process_Manager::set_scheduler_all ( const ACE_Sched_Params  ) 

Sets the scheduling parameters for all the <Process>es managed by <ACE_Process_Manager> by passing <params> to <ACE_OS::sched_params>. Returns 0 on success, -1 on failure.

pid_t ACE_Process_Manager::spawn ( ACE_Process_Options options,
ACE_Event_Handler event_handler = 0 
)

Create a new process by passing <options> to <ACE_Process::spawn>. Register <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 ACE_Process_Manager::spawn ( ACE_Process proc,
ACE_Process_Options options,
ACE_Event_Handler event_handler = 0 
)

Create a new process by passing <options> to <proc.spawn>. Register <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.

int ACE_Process_Manager::spawn_n ( size_t  n,
ACE_Process_Options options,
pid_t child_pids = 0,
ACE_Event_Handler event_Handler = 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. Register <event_handler> to be called back when each process exits. Returns 0 on success and -1 on failure.

int ACE_Process_Manager::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.

int ACE_Process_Manager::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.

pid_t ACE_Process_Manager::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 the class documentation 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.

pid_t ACE_Process_Manager::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 the class documentation 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.

int ACE_Process_Manager::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.


Friends And Related Function Documentation

friend class ACE_Process_Control [friend]


Member Data Documentation

ACE_Process_Manager::ACE_ALLOC_HOOK_DECLARE

Declare the dynamic allocation hooks.

size_t ACE_Process_Manager::current_count_ [private]

Current number of processes we are managing.

ACE_Event_Handler* ACE_Process_Manager::default_exit_handler_ [private]

This event handler is used to notify when a process we control exits.

int ACE_Process_Manager::delete_instance_ = 0 [static, private]

Controls whether the <Process_Manager> is deleted when we shut down (we can only delete it safely if we created it!)

ACE_Process_Manager * ACE_Process_Manager::instance_ = 0 [static, private]

Singleton pointer.

ACE_Recursive_Thread_Mutex ACE_Process_Manager::lock_ [private]

This lock protects access/ops on <process_table_>.

size_t ACE_Process_Manager::max_process_table_size_ [private]

Maximum number of processes we can manage (should be dynamically allocated).

ACE_Process_Descriptor* ACE_Process_Manager::process_table_ [private]

Vector that describes process state within the Process_Manager.


The documentation for this class was generated from the following files:
Generated on Sun Jul 9 09:24:47 2006 for ACE by  doxygen 1.4.7-1