#include <Process_Manager.h>
Inheritance diagram for ACE_Process_Manager:


Public Types | |
| 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 ¶ms, 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 | |
| ACE_Process_Manager * | instance (void) |
| Get pointer to a process-wide . | |
| ACE_Process_Manager * | instance (ACE_Process_Manager *) |
| void | close_singleton (void) |
| Delete the dynamically allocated singleton. | |
| 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_Descriptor * | process_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_Handler * | default_exit_handler_ |
| ACE_Recursive_Thread_Mutex | lock_ |
| This lock protects access/ops on . | |
Static Private Attributes | |
| ACE_Process_Manager * | instance_ = 0 |
| Singleton pointer. | |
| int | delete_instance_ = 0 |
Friends | |
| class | ACE_Process_Control |
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 es. If you just want es to go away when they're finished, simply register the with an <ACE_Reactor>: ACE_Process_Manager mgr( 100, some_reactor ) -or- ACE_Process_Manager mgr; ... mgr.open( 100, some_reactor ); Then, the will clean up after any 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 cleanup code, then *don't* register the with a Reactor, and be sure to call one of the <Process_Manager::wait> functions whenever there might be managed es that have exited. Note that in either case, allows you to register "<Event_Handlers>" to be called when a specific exits, or when any without a specific exits. When a exits, the appropriate 's 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 is registered with a . 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 whose you invoked. It's best to only use a single , and to create all subprocesses by calling that 's method. Incidentally, when you register your with a its notification pipe is used to help "reap" the available exit statuses. Therefore, you must not use a whose notify pipe has been disabled. Here's the sequence of steps used to reap the exit statuses in this case: + The registers a signal handler for SIGCHLD. + The SIGCHLD handler, when invoked, uses the 's method to inform the to wake up. + Next, the calls the 's , this happens synchronously, not in sighandler-space. + The method collects all available exit statuses.
Definition at line 124 of file Process_Manager.h.
|
|
Definition at line 129 of file Process_Manager.h.
00130 {
00131 DEFAULT_SIZE = 100
00132 };
|
|
||||||||||||
|
Initialize an with a table containing up to processes. This table resizes itself automatically as needed. If a non-NULL is provided, this uses it to notify an application when a process it controls exits. By default, however, we don't use an ACE_Reactor. Definition at line 246 of file Process_Manager.cpp. References ACE_ERROR, ACE_LIB_TEXT, ACE_TRACE, LM_ERROR, and open().
00248 : ACE_Event_Handler (), 00249 process_table_ (0), 00250 max_process_table_size_ (0), 00251 current_count_ (0), 00252 default_exit_handler_ (0) 00253 #if defined (ACE_HAS_THREADS) 00254 , lock_ () 00255 #endif /* ACE_HAS_THREADS */ 00256 { 00257 ACE_TRACE ("ACE_Process_Manager::ACE_Process_Manager"); 00258 00259 if (this->open (size, 00260 r) == -1) 00261 ACE_ERROR ((LM_ERROR, 00262 ACE_LIB_TEXT ("%p\n"), 00263 ACE_LIB_TEXT ("ACE_Process_Manager"))); 00264 } |
|
|
Destructor releases all resources and does not wait for processes to exit. Definition at line 301 of file Process_Manager.cpp. References ACE_TRACE, and close().
|
|
||||||||||||
|
Append information about a process, i.e., its in the . Each entry is added at the end, growing the table if necessary. Register to be called back when the process exits. Definition at line 497 of file Process_Manager.cpp. References ACE_TRACE, current_count_, DEFAULT_SIZE, ACE_Process_Descriptor::exit_notify_, ACE_Process::gethandle(), max_process_table_size_, ACE_Process_Descriptor::process_, process_table_, ACE_Event_Handler::reactor(), ACE_Reactor::register_handler(), and resize(). Referenced by insert_proc(), and spawn().
00499 {
00500 ACE_TRACE ("ACE_Process_Manager::append_proc");
00501
00502 // Try to resize the array to twice its existing size (or the DEFAULT_SIZE,
00503 // if there are no array entries) if we run out of space...
00504 if (this->current_count_ >= this->max_process_table_size_)
00505 {
00506 size_t new_size = this->max_process_table_size_ * 2;
00507 if (new_size == 0)
00508 new_size = ACE_Process_Manager::DEFAULT_SIZE;
00509 if (this->resize (new_size) == -1)
00510 return -1;
00511 }
00512
00513 ACE_Process_Descriptor &proc_desc =
00514 this->process_table_[this->current_count_];
00515
00516 proc_desc.process_ = proc;
00517 proc_desc.exit_notify_ = event_handler;
00518
00519 #if defined (ACE_WIN32)
00520 // If we have a Reactor, then we're supposed to reap Processes
00521 // automagically. Get a handle to this new Process and tell the
00522 // Reactor we're interested in <handling_input> on it.
00523
00524 ACE_Reactor * const r = this->reactor ();
00525 if (r != 0)
00526 r->register_handler (this, proc->gethandle ());
00527 #endif /* ACE_WIN32 */
00528
00529 ++this->current_count_;
00530 return 0;
00531 }
|
|
||||||||||||
|
Cleanup method, used by the to destroy the singleton. Definition at line 38 of file Process_Manager.cpp. References close_singleton(). Referenced by instance().
00039 {
00040 ACE_Process_Manager::close_singleton ();
00041 }
|
|
|
Release all resources. Do not wait for processes to exit.
Definition at line 269 of file Process_Manager.cpp. References ACE_GUARD_RETURN, ACE_TRACE, current_count_, default_exit_handler_, ACE_Event_Handler::handle_close(), max_process_table_size_, process_table_, ACE_Event_Handler::reactor(), ACE_Reactor::remove_handler(), remove_proc(), and SIGCHLD. Referenced by ~ACE_Process_Manager().
00270 {
00271 ACE_TRACE ("ACE_Process_Manager::close");
00272
00273 if (this->reactor () != 0)
00274 {
00275 #if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SIGNALS)
00276 this->reactor ()->remove_handler (SIGCHLD, (ACE_Sig_Action *) 0);
00277 #endif /* !ACE_WIN32 */
00278 this->reactor (0);
00279 }
00280
00281 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00282
00283 if (this->process_table_ != 0)
00284 {
00285 while (this->current_count_ > 0)
00286 this->remove_proc (0);
00287
00288 delete [] this->process_table_;
00289 this->process_table_ = 0;
00290 this->max_process_table_size_ = 0;
00291 this->current_count_ = 0;
00292 }
00293
00294 if (this->default_exit_handler_ != 0)
00295 this->default_exit_handler_->handle_close (ACE_INVALID_HANDLE,0);
00296 this->default_exit_handler_ = 0;
00297
00298 return 0;
00299 }
|
|
|
Delete the dynamically allocated singleton.
Definition at line 176 of file Process_Manager.cpp. References ACE_GUARD, ACE_TRACE, delete_instance_, and instance_. Referenced by cleanup().
00177 {
00178 ACE_TRACE ("ACE_Process_Manager::close_singleton");
00179
00180 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
00181 *ACE_Static_Object_Lock::instance ()));
00182
00183 if (ACE_Process_Manager::delete_instance_)
00184 {
00185 delete ACE_Process_Manager::instance_;
00186 ACE_Process_Manager::instance_ = 0;
00187 ACE_Process_Manager::delete_instance_ = 0;
00188 }
00189 }
|
|
|
Dump the state of an object.
Definition at line 84 of file Process_Manager.cpp. References ACE_BEGIN_DUMP, ACE_DEBUG, ACE_END_DUMP, ACE_LIB_TEXT, ACE_TRACE, current_count_, ACE_Process_Descriptor::dump(), LM_DEBUG, and process_table_.
00085 {
00086 #if defined (ACE_HAS_DUMP)
00087 ACE_TRACE ("ACE_Process_Manager::dump");
00088
00089 ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00090
00091 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmax_process_table_size_ = %d"), this->max_process_table_size_));
00092 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ncurrent_count_ = %d"), this->current_count_));
00093
00094 for (size_t i = 0; i < this->current_count_; i++)
00095 this->process_table_[i].dump ();
00096
00097 ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00098 #endif /* ACE_HAS_DUMP */
00099 }
|
|
|
Locate the index of the table slot occupied by . Returns ~0 if is not in the Definition at line 715 of file Process_Manager.cpp. References ACE_TRACE, current_count_, ACE_Process::gethandle(), ACE_Process_Descriptor::process_, and process_table_.
00716 {
00717 ACE_TRACE ("ACE_Process_Manager::find_proc");
00718
00719 for (size_t i = 0; i < this->current_count_; ++i)
00720 if (h == this->process_table_[i].process_->gethandle ())
00721 return i;
00722
00723 return -1;
00724 }
|
|
|
Locate the index of the table slot occupied by . Returns -1 if is not in the Definition at line 699 of file Process_Manager.cpp. References ACE_TRACE, current_count_, ACE_Process::getpid(), pid_t, ACE_Process_Descriptor::process_, and process_table_. Referenced by handle_signal(), insert_proc(), register_handler(), remove(), set_scheduler(), terminate(), and wait().
00700 {
00701 ACE_TRACE ("ACE_Process_Manager::find_proc");
00702
00703 for (size_t i = 0; i < this->current_count_; ++i)
00704 if (pid == this->process_table_[i].process_->getpid ())
00705 return i;
00706
00707 return -1;
00708 }
|
|
||||||||||||||||
|
On Unix, this routine is called asynchronously when a SIGCHLD is received. We just tweak the reactor so that it'll call back our 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. Definition at line 341 of file Process_Manager.cpp. References ACE_ERROR_RETURN, ACE_exitcode, ACE_GUARD_RETURN, ACE_INVALID_PID, ACE_LIB_TEXT, find_proc(), ACE_Process::getpid(), LM_ERROR, ACE_Reactor::notify(), notify_proc_handler(), pid_t, ACE_Process_Descriptor::process_, process_table_, ACE_Event_Handler::reactor(), remove_proc(), siginfo_t::si_handle_, ssize_t, and ucontext_t.
00344 {
00345 #if defined (ACE_WIN32)
00346 ACE_HANDLE proc = si->si_handle_;
00347 ACE_exitcode status = 0;
00348 BOOL result = ::GetExitCodeProcess (proc,
00349 &status);
00350 if (result)
00351 {
00352 if (status != STILL_ACTIVE)
00353 {
00354 {
00355 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, lock_, -1));
00356
00357 ssize_t const i = this->find_proc (proc);
00358 if (i == -1)
00359 return -1;
00360 #if 0
00361 pid_t pid = i != -1
00362 ? process_table_[i].process_->getpid ()
00363 : ACE_INVALID_PID;
00364 #endif
00365 this->notify_proc_handler (i, status);
00366 this->remove_proc (i);
00367 }
00368 return -1; // remove this HANDLE/Event_Handler combination
00369 }
00370 else
00371 ACE_ERROR_RETURN ((LM_ERROR,
00372 ACE_LIB_TEXT ("Process still active")
00373 ACE_LIB_TEXT (" -- shouldn't have been called yet!\n")),
00374 0); // return 0 : stay registered
00375 }
00376 else
00377 {
00378 // <GetExitCodeProcess> failed.
00379 ACE_ERROR_RETURN ((LM_ERROR,
00380 ACE_LIB_TEXT ("GetExitCodeProcess failed")),
00381 -1); // return -1: unregister
00382 }
00383 #else /* !ACE_WIN32 */
00384 ACE_UNUSED_ARG (si);
00385 return reactor ()->notify (this, ACE_Event_Handler::READ_MASK);
00386 #endif /* !ACE_WIN32 */
00387 }
|
|
||||||||||||
|
Insert a process in the table (checks for duplicates). Omitting the process handle won't work on Win32... Register to be called back when the process exits. Definition at line 537 of file Process_Manager.cpp. References ACE_TRACE, append_proc(), find_proc(), and ACE_Process::getpid().
00539 {
00540 ACE_TRACE ("ACE_Process_Manager::insert_proc");
00541
00542 // Check for duplicates and bail out if they're already
00543 // registered...
00544 if (this->find_proc (proc->getpid ()) != -1)
00545 return -1;
00546
00547 return this->append_proc (proc, event_handler);
00548 }
|
|
|
Set pointer to a process-wide and return existing pointer. Definition at line 147 of file Process_Manager.cpp. References ACE_GUARD_RETURN, ACE_TRACE, ACE_Object_Manager::at_exit(), cleanup(), delete_instance_, and instance_.
00148 {
00149 ACE_TRACE ("ACE_Process_Manager::instance");
00150 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
00151 *ACE_Static_Object_Lock::instance (), 0));
00152
00153 ACE_Process_Manager *t = ACE_Process_Manager::instance_;
00154 // We can't safely delete it since we don't know who created it!
00155 ACE_Process_Manager::delete_instance_ = 0;
00156
00157 // Register with the Object_Manager so that the wrapper to
00158 // delete the proactor will be called when Object_Manager is
00159 // being terminated.
00160
00161 #if defined ACE_HAS_SIG_C_FUNC
00162 ACE_Object_Manager::at_exit (ACE_Process_Manager::instance_,
00163 ACE_Process_Manager_cleanup,
00164 0);
00165 #else
00166 ACE_Object_Manager::at_exit (ACE_Process_Manager::instance_,
00167 ACE_Process_Manager::cleanup,
00168 0);
00169 #endif /* ACE_HAS_SIG_C_FUNC */
00170
00171 ACE_Process_Manager::instance_ = tm;
00172 return t;
00173 }
|
|
|
Get pointer to a process-wide .
Definition at line 109 of file Process_Manager.cpp. References ACE_GUARD_RETURN, ACE_NEW_RETURN, ACE_TRACE, ACE_Object_Manager::at_exit(), cleanup(), delete_instance_, and instance_.
00110 {
00111 ACE_TRACE ("ACE_Process_Manager::instance");
00112
00113 if (ACE_Process_Manager::instance_ == 0)
00114 {
00115 // Perform Double-Checked Locking Optimization.
00116 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
00117 *ACE_Static_Object_Lock::instance (), 0));
00118
00119 if (ACE_Process_Manager::instance_ == 0)
00120 {
00121 ACE_NEW_RETURN (ACE_Process_Manager::instance_,
00122 ACE_Process_Manager,
00123 0);
00124 ACE_Process_Manager::delete_instance_ = 1;
00125
00126 // Register with the Object_Manager so that the wrapper to
00127 // delete the proactor will be called when Object_Manager is
00128 // being terminated.
00129
00130 #if defined ACE_HAS_SIG_C_FUNC
00131 ACE_Object_Manager::at_exit (ACE_Process_Manager::instance_,
00132 ACE_Process_Manager_cleanup,
00133 0);
00134 #else
00135 ACE_Object_Manager::at_exit (ACE_Process_Manager::instance_,
00136 ACE_Process_Manager::cleanup,
00137 0);
00138 #endif /* ACE_HAS_SIG_C_FUNC */
00139
00140 }
00141 }
00142
00143 return ACE_Process_Manager::instance_;
00144 }
|
|
|
Return the number of managed Processes.
Definition at line 8 of file Process_Manager.inl. References current_count_.
00009 {
00010 return current_count_;
00011 }
|
|
||||||||||||
|
If there's a specific handler for the Process at index in the table, or there's a default handler, call it. Definition at line 1001 of file Process_Manager.cpp. References ACE_DEBUG, ACE_exitcode, ACE_LIB_TEXT, current_count_, default_exit_handler_, ACE_Process::exit_code(), ACE_Process_Descriptor::exit_notify_, ACE_Event_Handler::handle_close(), ACE_Event_Handler::handle_exit(), LM_DEBUG, ACE_Process_Descriptor::process_, and process_table_. Referenced by handle_signal(), and wait().
01003 {
01004 if (i < this->current_count_)
01005 {
01006 ACE_Process_Descriptor &proc_desc =
01007 this->process_table_[i];
01008
01009 proc_desc.process_->exit_code (exit_code);
01010
01011 if (proc_desc.exit_notify_ != 0)
01012 proc_desc.exit_notify_->handle_exit (proc_desc.process_);
01013 else if (this->default_exit_handler_ != 0
01014 && this->default_exit_handler_->handle_exit (proc_desc.process_) < 0)
01015 {
01016 this->default_exit_handler_->handle_close
01017 (ACE_INVALID_HANDLE,
01018 0);
01019 this->default_exit_handler_ = 0;
01020 }
01021 return 1;
01022 }
01023 else
01024 {
01025 ACE_DEBUG ((LM_DEBUG,
01026 ACE_LIB_TEXT ("(%P:%t|%T) ACE_Process_Manager::notify_proc_handler:")
01027 ACE_LIB_TEXT (" unknown/unmanaged process reaped\n")));
01028 return 0;
01029 }
01030 }
|
|
||||||||||||
|
Initialize an with a table containing up to processes. This table resizes itself automatically as needed. If a non-NULL is provided, this uses it to notify an application when a process it controls exits. By default, however, we don't use an ACE_Reactor. Definition at line 222 of file Process_Manager.cpp. References ACE_GUARD_RETURN, ACE_TRACE, max_process_table_size_, ACE_Event_Handler::reactor(), ACE_Reactor::register_handler(), resize(), and SIGCHLD. Referenced by ACE_Process_Manager().
00224 {
00225 ACE_TRACE ("ACE_Process_Manager::open");
00226
00227 if (r)
00228 {
00229 this->reactor (r);
00230 #if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SIGNALS)
00231 // Register signal handler object.
00232 if (r->register_handler (SIGCHLD, this) == -1)
00233 return -1;
00234 #endif /* !defined(ACE_WIN32) */
00235 }
00236
00237 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00238
00239 if (this->max_process_table_size_ < size)
00240 this->resize (size);
00241 return 0;
00242 }
|
|
||||||||||||||||
|
Definition at line 983 of file Process_Manager.cpp. References ACE_BIT_ENABLED, ACE_exitcode, ACE_TRACE, pid_t, wait(), and WNOHANG.
|
|
||||||||||||
|
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.
Definition at line 390 of file Process_Manager.cpp. References ACE_GUARD_RETURN, ACE_INVALID_PID, default_exit_handler_, ACE_Process_Descriptor::exit_notify_, find_proc(), ACE_Event_Handler::handle_close(), pid_t, process_table_, and ssize_t.
00392 {
00393 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00394
00395 if (pid == ACE_INVALID_PID)
00396 {
00397 if (this->default_exit_handler_ != 0)
00398 this->default_exit_handler_->handle_close (ACE_INVALID_HANDLE, 0);
00399 this->default_exit_handler_ = eh;
00400 return 0;
00401 }
00402
00403 ssize_t const i = this->find_proc (pid);
00404
00405 if (i == -1)
00406 {
00407 errno = EINVAL;
00408 return -1;
00409 }
00410
00411 ACE_Process_Descriptor &proc_desc = this->process_table_[i];
00412
00413 if (proc_desc.exit_notify_ != 0)
00414 proc_desc.exit_notify_->handle_close (ACE_INVALID_HANDLE, 0);
00415 proc_desc.exit_notify_ = eh;
00416 return 0;
00417 }
|
|
|
Remove process from the table. This is called automatically by the method after it successfully reaped a signal. It's also possible to call this method directly from a signal handler, but don't call both and ! Definition at line 553 of file Process_Manager.cpp. References ACE_GUARD_RETURN, ACE_TRACE, find_proc(), pid_t, remove_proc(), and ssize_t. Referenced by wait().
00554 {
00555 ACE_TRACE ("ACE_Process_Manager::remove");
00556
00557 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00558
00559 ssize_t const i = this->find_proc (pid);
00560
00561 if (i != -1)
00562 return this->remove_proc (i);
00563
00564 // set "process not found" error
00565 return -1;
00566 }
|
|
|
Actually removes the process at index from the table. This method must be called with locks held. Definition at line 571 of file Process_Manager.cpp. References ACE_TRACE, current_count_, ACE_Process_Descriptor::exit_notify_, ACE_Process::gethandle(), ACE_Event_Handler::handle_close(), ACE_Process_Descriptor::process_, process_table_, ACE_Event_Handler::reactor(), ACE_Reactor::remove_handler(), and ACE_Process::unmanage(). Referenced by close(), handle_signal(), remove(), terminate(), and wait().
00572 {
00573 ACE_TRACE ("ACE_Process_Manager::remove_proc");
00574
00575 // If there's an exit_notify_ <Event_Handler> for this pid, call its
00576 // <handle_close> method.
00577
00578 if (this->process_table_[i].exit_notify_ != 0)
00579 {
00580 this->process_table_[i].exit_notify_->handle_close
00581 (this->process_table_[i].process_->gethandle(),
00582 0);
00583 this->process_table_[i].exit_notify_ = 0;
00584 }
00585
00586 #if defined (ACE_WIN32)
00587 ACE_Reactor * const r = this->reactor ();
00588 if (r != 0)
00589 r->remove_handler (this->process_table_[i].process_->gethandle (),
00590 ACE_Event_Handler::DONT_CALL);
00591 #endif /* ACE_WIN32 */
00592
00593 this->process_table_[i].process_->unmanage ();
00594
00595 this->process_table_[i].process_ = 0;
00596
00597 this->current_count_--;
00598
00599 if (this->current_count_ > 0)
00600 // Compact the table by moving the last item into the slot vacated
00601 // by the index being removed (this is a structure assignment).
00602 this->process_table_[i] =
00603 this->process_table_[this->current_count_];
00604
00605 return 0;
00606 }
|
|
|
Resize the pool of Process_Descriptors.
Definition at line 192 of file Process_Manager.cpp. References ACE_NEW_RETURN, ACE_TRACE, current_count_, max_process_table_size_, and process_table_. Referenced by append_proc(), and open().
00193 {
00194 ACE_TRACE ("ACE_Process_Manager::resize");
00195
00196 if (size <= this->max_process_table_size_)
00197 return 0;
00198
00199 ACE_Process_Descriptor *temp = 0;
00200
00201 ACE_NEW_RETURN (temp,
00202 ACE_Process_Descriptor[size],
00203 -1);
00204
00205 for (size_t i = 0;
00206 i < this->current_count_;
00207 i++)
00208 // Structure assignment.
00209 temp[i] = this->process_table_[i];
00210
00211 this->max_process_table_size_ = size;
00212
00213 delete [] this->process_table_;
00214
00215 this->process_table_ = temp;
00216 return 0;
00217 }
|
|
||||||||||||
|
Sets the scheduling parameters for the managed by identified by pid by passing , to <ACE_OS::sched_params>. Returns 0 on success, -1 on failure, and ACE_INVALID_PID when given pid is not managed by . Definition at line 657 of file Process_Manager.cpp. References ACE_GUARD_RETURN, ACE_INVALID_PID, ACE_TRACE, find_proc(), pid_t, ACE_OS::sched_params(), and ssize_t.
00659 {
00660 ACE_TRACE ("ACE_Process_Manager::set_scheduler");
00661
00662 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
00663 ace_mon, this->lock_, -1));
00664
00665 // Check to see if the process identified by the given pid is managed by
00666 // this instance of ACE_Process_Manager.
00667 ssize_t const i = this->find_proc (pid);
00668
00669 if (i == -1)
00670 // set "no such process" error
00671 return ACE_INVALID_PID;
00672
00673 return ACE_OS::sched_params (params, pid);
00674 }
|
|
|
Sets the scheduling parameters for all the es managed by by passing to <ACE_OS::sched_params>. Returns 0 on success, -1 on failure. Definition at line 677 of file Process_Manager.cpp. References ACE_GUARD_RETURN, ACE_TRACE, current_count_, ACE_Process::getpid(), pid_t, ACE_Process_Descriptor::process_, process_table_, and ACE_OS::sched_params().
00678 {
00679 ACE_TRACE ("ACE_Process_Manager::set_scheduler_all");
00680
00681 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
00682 ace_mon, this->lock_, -1));
00683
00684 for (size_t i = 0; i < this->current_count_; ++i)
00685 {
00686 pid_t const pid = this->process_table_[i].process_->getpid ();
00687 if (ACE_OS::sched_params (params, pid) != 0)
00688 return -1;
00689 }
00690 return 0;
00691
00692 }
|
|
||||||||||||
|
Create a new process by passing to <ACE_Process::spawn>. Register 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. Definition at line 422 of file Process_Manager.cpp. References ACE_INVALID_PID, ACE_NEW_RETURN, pid_t, and spawn().
00424 {
00425 ACE_Process *process = 0;
00426 ACE_NEW_RETURN (process,
00427 ACE_Managed_Process,
00428 ACE_INVALID_PID);
00429
00430 pid_t const pid = spawn (process, options, event_handler);
00431 if (pid == ACE_INVALID_PID || pid == 0)
00432 delete process;
00433
00434 return pid;
00435 }
|
|
||||||||||||||||
|
Create a new process by passing to <proc.spawn>. Register 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. Definition at line 440 of file Process_Manager.cpp. References ACE_GUARD_RETURN, ACE_INVALID_PID, ACE_TRACE, append_proc(), pid_t, and ACE_Process::spawn(). Referenced by spawn(), and spawn_n().
00443 {
00444 ACE_TRACE ("ACE_Process_Manager::spawn");
00445
00446 pid_t const pid = process->spawn (options);
00447
00448 // Only include the pid in the parent's table.
00449 if (pid == ACE_INVALID_PID || pid == 0)
00450 return pid;
00451
00452 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
00453 ace_mon, this->lock_, -1));
00454
00455 if (this->append_proc (process, event_handler) == -1)
00456 // bad news: spawned, but not registered in table.
00457 return ACE_INVALID_PID;
00458
00459 return pid;
00460 }
|
|
||||||||||||||||||||
|
Create new processes by passing to <ACE_Process::spawn>, which is called times. If is non-0 it is expected to be an array of 's, which are filled in with the process ids of each newly created process. Register to be called back when each process exits. Returns 0 on success and -1 on failure. Definition at line 465 of file Process_Manager.cpp. References ACE_INVALID_PID, ACE_TRACE, pid_t, and spawn().
00469 {
00470 ACE_TRACE ("ACE_Process_Manager::spawn_n");
00471
00472 if (child_pids != 0)
00473 for (size_t i = 0;
00474 i < n;
00475 ++i)
00476 child_pids[i] = ACE_INVALID_PID;
00477
00478 for (size_t i = 0;
00479 i < n;
00480 i++)
00481 {
00482 pid_t const pid = this->spawn (options, event_handler);
00483 if (pid == ACE_INVALID_PID || pid == 0)
00484 // We're in the child or something's gone wrong.
00485 return pid;
00486 else if (child_pids != 0)
00487 child_pids[i] = pid;
00488 }
00489
00490 return 0;
00491 }
|
|
||||||||||||
|
On OSs that support signals, send the signal to the specified process. Returns 0 on success and -1 on failure. Definition at line 637 of file Process_Manager.cpp. References ACE_GUARD_RETURN, ACE_TRACE, find_proc(), ACE_OS::kill(), pid_t, and ssize_t.
00639 {
00640 ACE_TRACE ("ACE_Process_Manager::terminate");
00641
00642 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00643
00644 // Check for duplicates and bail out if they're already
00645 // registered...
00646 ssize_t const i = this->find_proc (pid);
00647
00648 if (i == -1)
00649 // set "no such process" error
00650 return -1;
00651
00652 return ACE_OS::kill (pid, sig);
00653 }
|
|
|
Abruptly terminate a single process with id 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. Definition at line 609 of file Process_Manager.cpp. References ACE_GUARD_RETURN, ACE_TRACE, find_proc(), pid_t, remove_proc(), ssize_t, and ACE::terminate_process().
00610 {
00611 ACE_TRACE ("ACE_Process_Manager::terminate");
00612
00613 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00614
00615 // Check for duplicates and bail out if they're already
00616 // registered...
00617 ssize_t const i = this->find_proc (pid);
00618
00619 if (i == -1)
00620 // set "no such process" error
00621 return -1;
00622
00623 int const result = ACE::terminate_process (pid);
00624
00625 if (result != -1)
00626 {
00627 // Save/restore errno.
00628 ACE_Errno_Guard error (errno);
00629 this->remove_proc (i);
00630 return 0;
00631 }
00632
00633 return -1;
00634 }
|
|
||||||||||||
|
Wait indefinitely for a single process to terminate. If pid==0, waits for any of the managed es (but see the note in the class documentation for caveats about this -- "sloppy Process cleanup on unix") If pid != 0, waits for that only. Returns the pid of the process whose exit was handled, or ACE_INVALID_PID on error. Definition at line 770 of file Process_Manager.cpp. References ACE_exitcode, ACE_TRACE, pid_t, and wait().
|
|
||||||||||||||||
|
Wait up to for a single process to terminate. If pid==0, waits for any of the managed 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 only. Returns the pid of the Process whose exit was handled, 0 if a timeout occurred, or ACE_INVALID_PID on error. Definition at line 785 of file Process_Manager.cpp. References ACE_ASSERT, ACE_DEBUG, ACE_ERROR_RETURN, ACE_exitcode, ACE_GUARD_RETURN, ACE_INVALID_PID, ACE_LIB_TEXT, ACE_NEW_RETURN, ACE_SignalHandler, ACE_TRACE, current_count_, find_proc(), ACE_Process::gethandle(), ACE_Process::getpid(), LM_DEBUG, LM_ERROR, ACE_Time_Value::msec(), notify_proc_handler(), pid_t, ACE_Process_Descriptor::process_, process_table_, ACE_Event_Handler::reactor(), ACE_Sig_Action::register_action(), remove(), remove_proc(), SIGCHLD, ACE_OS::sleep(), ssize_t, ACE_Countdown_Time::update(), ACE_Process::wait(), ACE_OS::waitpid(), and WNOHANG.
00788 {
00789 ACE_TRACE ("ACE_Process_Manager::wait");
00790
00791 ACE_exitcode local_stat = 0;
00792 if (status == 0)
00793 status = &local_stat;
00794
00795 *status = 0;
00796
00797 ssize_t idx = -1;
00798 ACE_Process *proc = 0;
00799
00800 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00801
00802 if (pid != 0)
00803 {
00804 idx = this->find_proc (pid);
00805 if (idx == -1)
00806 return ACE_INVALID_PID;
00807 else
00808 proc = process_table_[idx].process_;
00809 }
00810
00811 if (proc != 0)
00812 pid = proc->wait (timeout, status);
00813 else
00814 {
00815 // Wait for any Process spawned by this Process_Manager.
00816 #if defined (ACE_WIN32)
00817 HANDLE *handles = 0;
00818
00819 ACE_NEW_RETURN (handles,
00820 HANDLE[this->current_count_],
00821 ACE_INVALID_PID);
00822
00823 for (size_t i = 0;
00824 i < this->current_count_;
00825 ++i)
00826 handles[i] =
00827 process_table_[i].process_->gethandle ();
00828
00829 DWORD handle_count = static_cast<DWORD> (this->current_count_);
00830 DWORD result = ::WaitForMultipleObjects (handle_count,
00831 handles,
00832 FALSE,
00833 timeout == ACE_Time_Value::max_time
00834 ? INFINITE
00835 : timeout.msec ());
00836 if (result == WAIT_FAILED)
00837 pid = ACE_INVALID_PID;
00838 else if (result == WAIT_TIMEOUT)
00839 pid = 0;
00840 else
00841 {
00842 // Green Hills produces a warning that result >= WAIT_OBJECT_0 is
00843 // a pointless comparison because WAIT_OBJECT_0 is zero and DWORD is
00844 // unsigned long, so this test is skipped for Green Hills.
00845 // Same for mingw.
00846 # if defined (ghs) || defined (__MINGW32__) || (defined (_MSC_VER) && _MSC_VER >= 1300)
00847 ACE_ASSERT (result < WAIT_OBJECT_0 + this->current_count_);
00848 # else
00849 ACE_ASSERT (result >= WAIT_OBJECT_0
00850 && result < WAIT_OBJECT_0 + this->current_count_);
00851 # endif
00852
00853 idx = this->find_proc (handles[result - WAIT_OBJECT_0]);
00854
00855 if (idx != -1)
00856 {
00857 pid = process_table_[idx].process_->getpid ();
00858 result = ::GetExitCodeProcess (handles[result - WAIT_OBJECT_0],
00859 status);
00860 if (result == 0)
00861 {
00862 // <GetExitCodeProcess> failed!
00863 this->remove_proc (idx);
00864 pid = ACE_INVALID_PID;
00865 }
00866 }
00867 else
00868 {
00869 // uh oh...handle removed from process_table_, even though
00870 // we're holding a lock!
00871 delete [] handles;
00872 ACE_ERROR_RETURN ((LM_ERROR,
00873 ACE_LIB_TEXT ("Process removed")
00874 ACE_LIB_TEXT (" -- somebody's ignoring the lock!\n")),
00875 -1);
00876 }
00877 }
00878
00879 delete [] handles;
00880 #else /* !defined(ACE_WIN32) */
00881 if (timeout == ACE_Time_Value::max_time)
00882 {
00883 pid = ACE_OS::waitpid (-1, status, 0);
00884 }
00885 else if (timeout == ACE_Time_Value::zero)
00886 {
00887 pid = ACE_OS::waitpid (-1, status, WNOHANG);
00888 }
00889 else
00890 {
00891 # if defined (ACE_LACKS_UNIX_SIGNALS)
00892 pid = 0;
00893 ACE_Time_Value sleeptm (1); // 1 msec
00894 if (sleeptm > timeout) // if sleeptime > waittime
00895 sleeptm = timeout;
00896 ACE_Time_Value tmo (timeout); // Need one we can change
00897 for (ACE_Countdown_Time time_left (&tmo); tmo > ACE_Time_Value::zero ; time_left.update ())
00898 {
00899 pid = ACE_OS::waitpid (-1, status, WNOHANG);
00900 if (pid > 0 || pid == ACE_INVALID_PID)
00901 break; // Got a child or an error - all done
00902
00903 // pid 0, nothing is ready yet, so wait.
00904 // Do a (very) short sleep (only this thread sleeps).
00905 ACE_OS::sleep (sleeptm);
00906 }
00907 # else
00908 // Force generation of SIGCHLD, even though we don't want to
00909 // catch it - just need it to interrupt the sleep below.
00910 // If this object has a reactor set, assume it was given at
00911 // open(), and there's already a SIGCHLD action set, so no
00912 // action is needed here.
00913 ACE_Sig_Action old_action;
00914 if (this->reactor () == 0)
00915 {
00916 ACE_Sig_Action do_sigchld ((ACE_SignalHandler)sigchld_nop);
00917 do_sigchld.register_action (SIGCHLD, &old_action);
00918 }
00919
00920 ACE_Time_Value tmo (timeout); // Need one we can change
00921 for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
00922 {
00923 pid = ACE_OS::waitpid (-1, status, WNOHANG);
00924 # if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)
00925 if (pid > 0 || (pid == ACE_INVALID_PID && errno != EINTR))
00926 # else
00927 if (pid > 0 || pid == ACE_INVALID_PID)
00928 # endif
00929 break; // Got a child or an error - all done
00930
00931 // pid 0, nothing is ready yet, so wait.
00932 // Do a sleep (only this thread sleeps) til something
00933 // happens. This relies on SIGCHLD interrupting the sleep.
00934 // If SIGCHLD isn't delivered, we'll need to do something
00935 // with sigaction to force it.
00936 if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
00937 continue;
00938 // Timed out
00939 pid = 0;
00940 break;
00941 }
00942
00943 // Restore the previous SIGCHLD action if it was changed.
00944 if (this->reactor () == 0)
00945 {
00946 old_action.register_action (SIGCHLD);
00947 }
00948 # endif /* !ACE_LACKS_UNIX_SIGNALS */
00949 }
00950 #endif /* !defined (ACE_WIN32) */
00951 }
00952
00953 if (pid != ACE_INVALID_PID && pid != 0)
00954 {
00955 if (proc == 0)
00956 {
00957 idx = this->find_proc (pid);
00958 if (idx == -1)
00959 {
00960 // oops, reaped an unmanaged process!
00961 ACE_DEBUG ((LM_DEBUG,
00962 ACE_LIB_TEXT ("(%P|%t) oops, reaped unmanaged %d\n"),
00963 pid));
00964 return pid;
00965 }
00966 else
00967 proc = process_table_[idx].process_;
00968 }
00969 else
00970 ACE_ASSERT (pid == proc->getpid ());
00971
00972 this->notify_proc_handler (idx,
00973 *status);
00974 this->remove (pid);
00975 }
00976
00977 return pid;
00978 }
|
|
|
Block until there are no more child processes running that were ed by this . Unlike the 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 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 s the corresponding entries from the ; otherwise, returns -1 on failure. Definition at line 731 of file Process_Manager.cpp. References ACE_INVALID_PID, ACE_TRACE, current_count_, ACE_OS::gettimeofday(), and pid_t. Referenced by reap(), and wait().
00732 {
00733 ACE_TRACE ("ACE_Process_Manager::wait");
00734
00735 ACE_Time_Value until = timeout;
00736 ACE_Time_Value remaining = timeout;
00737
00738 if (until < ACE_Time_Value::max_time)
00739 until += ACE_OS::gettimeofday ();
00740
00741 while (this->current_count_ > 0)
00742 {
00743 pid_t const pid = this->wait (0, remaining);
00744
00745 if (pid == ACE_INVALID_PID) // wait() failed
00746 return -1;
00747 else if (pid == 0) // timeout
00748 break;
00749
00750 remaining = until < ACE_Time_Value::max_time
00751 ? until - ACE_OS::gettimeofday ()
00752 : ACE_Time_Value::max_time;
00753
00754 if (remaining <= ACE_Time_Value::zero)
00755 break;
00756
00757 // else Process terminated...wait for more...
00758 }
00759 return static_cast<int> (this->current_count_);
00760 }
|
|
|
Definition at line 127 of file Process_Manager.h. |
|
|
Declare the dynamic allocation hooks.
Definition at line 326 of file Process_Manager.h. |
|
|
Current number of processes we are managing.
Definition at line 416 of file Process_Manager.h. Referenced by append_proc(), close(), dump(), find_proc(), managed(), notify_proc_handler(), remove_proc(), resize(), set_scheduler_all(), and wait(). |
|
|
This event handler is used to notify when a process we control exits. Definition at line 420 of file Process_Manager.h. Referenced by close(), notify_proc_handler(), and register_handler(). |
|
|
Controls whether the is deleted when we shut down (we can only delete it safely if we created it!) Definition at line 62 of file Process_Manager.cpp. Referenced by close_singleton(), and instance(). |
|
|
Singleton pointer.
Definition at line 58 of file Process_Manager.cpp. Referenced by close_singleton(), and instance(). |
|
|
This lock protects access/ops on .
Definition at line 431 of file Process_Manager.h. |
|
|
Maximum number of processes we can manage (should be dynamically allocated). Definition at line 413 of file Process_Manager.h. Referenced by append_proc(), close(), open(), and resize(). |
|
|
Vector that describes process state within the Process_Manager.
Definition at line 409 of file Process_Manager.h. Referenced by append_proc(), close(), dump(), find_proc(), handle_signal(), notify_proc_handler(), register_handler(), remove_proc(), resize(), set_scheduler_all(), and wait(). |
1.3.6