00001
00002
00003
00004 #include "ace/Process_Manager.h"
00005
00006 #if !defined (__ACE_INLINE__)
00007 #include "ace/Process_Manager.inl"
00008 #endif
00009
00010 #include "ace/ACE.h"
00011 #include "ace/Guard_T.h"
00012 #include "ace/Process.h"
00013 #include "ace/Signal.h"
00014 #include "ace/Object_Manager.h"
00015 #include "ace/Log_Msg.h"
00016 #include "ace/Reactor.h"
00017 #include "ace/Countdown_Time.h"
00018 #include "ace/OS_NS_sys_wait.h"
00019 #include "ace/OS_NS_signal.h"
00020 #include "ace/OS_NS_unistd.h"
00021 #include "ace/OS_NS_sys_time.h"
00022
00023 ACE_RCSID (ace,
00024 Process_Manager,
00025 "$Id: Process_Manager.cpp 81046 2008-03-21 10:11:12Z johnnyw $")
00026
00027 #if defined (ACE_HAS_SIG_C_FUNC)
00028 extern "C" void
00029 ACE_Process_Manager_cleanup (void *instance, void *arg)
00030 {
00031 ACE_Process_Manager::cleanup (instance, arg);
00032 }
00033 #endif
00034
00035 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00036
00037 void
00038 ACE_Process_Manager::cleanup (void *, void *)
00039 {
00040 ACE_Process_Manager::close_singleton ();
00041 }
00042
00043
00044
00045
00046 #if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SIGNALS)
00047 static void
00048 sigchld_nop (int, siginfo_t *, ucontext_t *)
00049 {
00050 return;
00051 }
00052 #endif
00053
00054
00055 ACE_ALLOC_HOOK_DEFINE(ACE_Process_Manager)
00056
00057
00058 ACE_Process_Manager *ACE_Process_Manager::instance_ = 0;
00059
00060
00061
00062 bool ACE_Process_Manager::delete_instance_ = false;
00063
00064 ACE_Process_Manager::Process_Descriptor::~Process_Descriptor (void)
00065 {
00066 }
00067
00068 void
00069 ACE_Process_Manager::Process_Descriptor::dump (void) const
00070 {
00071 #if defined (ACE_HAS_DUMP)
00072 ACE_TRACE ("ACE_Process_Manager::Process_Descriptor::dump");
00073
00074 ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00075
00076 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nproc_id_ = %d"),
00077 this->process_->getpid( )));
00078
00079 ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00080 #endif
00081 }
00082
00083 void
00084 ACE_Process_Manager::dump (void) const
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_TEXT ("\nmax_process_table_size_ = %d"), this->max_process_table_size_));
00092 ACE_DEBUG ((LM_DEBUG, ACE_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
00099 }
00100
00101 ACE_Process_Manager::Process_Descriptor::Process_Descriptor (void)
00102 : process_ (0),
00103 exit_notify_ (0)
00104 {
00105 ACE_TRACE ("ACE_Process_Manager::Process_Descriptor::Process_Descriptor");
00106 }
00107
00108 ACE_Process_Manager *
00109 ACE_Process_Manager::instance (void)
00110 {
00111 ACE_TRACE ("ACE_Process_Manager::instance");
00112
00113 if (ACE_Process_Manager::instance_ == 0)
00114 {
00115
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_ = true;
00125
00126
00127
00128
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
00139
00140 }
00141 }
00142
00143 return ACE_Process_Manager::instance_;
00144 }
00145
00146 ACE_Process_Manager *
00147 ACE_Process_Manager::instance (ACE_Process_Manager *tm)
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
00155 ACE_Process_Manager::delete_instance_ = false;
00156
00157
00158
00159
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
00170
00171 ACE_Process_Manager::instance_ = tm;
00172 return t;
00173 }
00174
00175 void
00176 ACE_Process_Manager::close_singleton( void )
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_ = false;
00188 }
00189 }
00190
00191 int
00192 ACE_Process_Manager::resize (size_t size)
00193 {
00194 ACE_TRACE ("ACE_Process_Manager::resize");
00195
00196 if (size <= this->max_process_table_size_)
00197 return 0;
00198
00199 Process_Descriptor *temp = 0;
00200
00201 ACE_NEW_RETURN (temp,
00202 Process_Descriptor[size],
00203 -1);
00204
00205 for (size_t i = 0;
00206 i < this->current_count_;
00207 i++)
00208
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 }
00218
00219
00220
00221 int
00222 ACE_Process_Manager::open (size_t size, ACE_Reactor *r)
00223 {
00224 ACE_TRACE ("ACE_Process_Manager::open");
00225
00226 if (r)
00227 {
00228 this->reactor (r);
00229 #if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SIGNALS)
00230
00231 if (r->register_handler (SIGCHLD, this) == -1)
00232 return -1;
00233 #endif
00234 }
00235
00236 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00237
00238 if (this->max_process_table_size_ < size)
00239 this->resize (size);
00240 return 0;
00241 }
00242
00243
00244
00245 ACE_Process_Manager::ACE_Process_Manager (size_t size,
00246 ACE_Reactor *r)
00247 : ACE_Event_Handler (),
00248 process_table_ (0),
00249 max_process_table_size_ (0),
00250 current_count_ (0),
00251 default_exit_handler_ (0)
00252 #if defined (ACE_HAS_THREADS)
00253 , lock_ ()
00254 #endif
00255 {
00256 ACE_TRACE ("ACE_Process_Manager::ACE_Process_Manager");
00257
00258 if (this->open (size,
00259 r) == -1)
00260 ACE_ERROR ((LM_ERROR,
00261 ACE_TEXT ("%p\n"),
00262 ACE_TEXT ("ACE_Process_Manager")));
00263 }
00264
00265
00266
00267 int
00268 ACE_Process_Manager::close (void)
00269 {
00270 ACE_TRACE ("ACE_Process_Manager::close");
00271
00272 if (this->reactor () != 0)
00273 {
00274 #if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SIGNALS)
00275 this->reactor ()->remove_handler (SIGCHLD, (ACE_Sig_Action *) 0);
00276 #endif
00277 this->reactor (0);
00278 }
00279
00280 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00281
00282 if (this->process_table_ != 0)
00283 {
00284 while (this->current_count_ > 0)
00285 this->remove_proc (0);
00286
00287 delete [] this->process_table_;
00288 this->process_table_ = 0;
00289 this->max_process_table_size_ = 0;
00290 this->current_count_ = 0;
00291 }
00292
00293 if (this->default_exit_handler_ != 0)
00294 this->default_exit_handler_->handle_close (ACE_INVALID_HANDLE,0);
00295 this->default_exit_handler_ = 0;
00296
00297 return 0;
00298 }
00299
00300 ACE_Process_Manager::~ACE_Process_Manager (void)
00301 {
00302 ACE_TRACE ("ACE_Process_Manager::~ACE_Process_Manager");
00303 this->close ();
00304 }
00305
00306 #if !defined (ACE_WIN32)
00307
00308
00309
00310
00311
00312
00313
00314 int
00315 ACE_Process_Manager::handle_input (ACE_HANDLE)
00316 {
00317 ACE_TRACE ("ACE_Process_Manager::handle_input");
00318
00319 pid_t pid;
00320
00321 do
00322 pid = this->wait (0,
00323 ACE_Time_Value::zero);
00324 while (pid != 0 && pid != ACE_INVALID_PID);
00325
00326 return 0;
00327 }
00328
00329 #endif
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 int
00340 ACE_Process_Manager::handle_signal (int,
00341 siginfo_t *si,
00342 ucontext_t *)
00343 {
00344 #if defined (ACE_WIN32)
00345 ACE_HANDLE proc = si->si_handle_;
00346 ACE_exitcode status = 0;
00347 BOOL result = ::GetExitCodeProcess (proc,
00348 &status);
00349 if (result)
00350 {
00351 if (status != STILL_ACTIVE)
00352 {
00353 {
00354 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, lock_, -1));
00355
00356 ssize_t const i = this->find_proc (proc);
00357 if (i == -1)
00358 return -1;
00359 #if 0
00360 pid_t pid = i != -1
00361 ? process_table_[i].process_->getpid ()
00362 : ACE_INVALID_PID;
00363 #endif
00364 this->notify_proc_handler (i, status);
00365 this->remove_proc (i);
00366 }
00367 return -1;
00368 }
00369 else
00370 ACE_ERROR_RETURN ((LM_ERROR,
00371 ACE_TEXT ("Process still active")
00372 ACE_TEXT (" -- shouldn't have been called yet!\n")),
00373 0);
00374 }
00375 else
00376 {
00377
00378 ACE_ERROR_RETURN ((LM_ERROR,
00379 ACE_TEXT ("GetExitCodeProcess failed")),
00380 -1);
00381 }
00382 #else
00383 ACE_UNUSED_ARG (si);
00384 return reactor ()->notify (this, ACE_Event_Handler::READ_MASK);
00385 #endif
00386 }
00387
00388 int
00389 ACE_Process_Manager::register_handler (ACE_Event_Handler *eh,
00390 pid_t pid)
00391 {
00392 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00393
00394 if (pid == ACE_INVALID_PID)
00395 {
00396 if (this->default_exit_handler_ != 0)
00397 this->default_exit_handler_->handle_close (ACE_INVALID_HANDLE, 0);
00398 this->default_exit_handler_ = eh;
00399 return 0;
00400 }
00401
00402 ssize_t const i = this->find_proc (pid);
00403
00404 if (i == -1)
00405 {
00406 errno = EINVAL;
00407 return -1;
00408 }
00409
00410 Process_Descriptor &proc_desc = this->process_table_[i];
00411
00412 if (proc_desc.exit_notify_ != 0)
00413 proc_desc.exit_notify_->handle_close (ACE_INVALID_HANDLE, 0);
00414 proc_desc.exit_notify_ = eh;
00415 return 0;
00416 }
00417
00418
00419
00420 pid_t
00421 ACE_Process_Manager::spawn (ACE_Process_Options &options,
00422 ACE_Event_Handler *event_handler)
00423 {
00424 ACE_Process *process = 0;
00425 ACE_NEW_RETURN (process,
00426 ACE_Managed_Process,
00427 ACE_INVALID_PID);
00428
00429 pid_t const pid = spawn (process, options, event_handler);
00430 if (pid == ACE_INVALID_PID || pid == 0)
00431 delete process;
00432
00433 return pid;
00434 }
00435
00436
00437
00438 pid_t
00439 ACE_Process_Manager::spawn (ACE_Process *process,
00440 ACE_Process_Options &options,
00441 ACE_Event_Handler *event_handler)
00442 {
00443 ACE_TRACE ("ACE_Process_Manager::spawn");
00444
00445 pid_t const pid = process->spawn (options);
00446
00447
00448 if (pid == ACE_INVALID_PID || pid == 0)
00449 return pid;
00450
00451 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
00452 ace_mon, this->lock_, -1));
00453
00454 if (this->append_proc (process, event_handler) == -1)
00455
00456 return ACE_INVALID_PID;
00457
00458 return pid;
00459 }
00460
00461
00462
00463 int
00464 ACE_Process_Manager::spawn_n (size_t n,
00465 ACE_Process_Options &options,
00466 pid_t *child_pids,
00467 ACE_Event_Handler *event_handler)
00468 {
00469 ACE_TRACE ("ACE_Process_Manager::spawn_n");
00470
00471 if (child_pids != 0)
00472 for (size_t i = 0;
00473 i < n;
00474 ++i)
00475 child_pids[i] = ACE_INVALID_PID;
00476
00477 for (size_t i = 0;
00478 i < n;
00479 i++)
00480 {
00481 pid_t const pid = this->spawn (options, event_handler);
00482 if (pid == ACE_INVALID_PID || pid == 0)
00483
00484 return pid;
00485 else if (child_pids != 0)
00486 child_pids[i] = pid;
00487 }
00488
00489 return 0;
00490 }
00491
00492
00493
00494
00495 int
00496 ACE_Process_Manager::append_proc (ACE_Process *proc,
00497 ACE_Event_Handler *event_handler)
00498 {
00499 ACE_TRACE ("ACE_Process_Manager::append_proc");
00500
00501
00502
00503 if (this->current_count_ >= this->max_process_table_size_)
00504 {
00505 size_t new_size = this->max_process_table_size_ * 2;
00506 if (new_size == 0)
00507 new_size = ACE_Process_Manager::DEFAULT_SIZE;
00508 if (this->resize (new_size) == -1)
00509 return -1;
00510 }
00511
00512 Process_Descriptor &proc_desc =
00513 this->process_table_[this->current_count_];
00514
00515 proc_desc.process_ = proc;
00516 proc_desc.exit_notify_ = event_handler;
00517
00518 #if defined (ACE_WIN32)
00519
00520
00521
00522 ACE_Reactor * const r = this->reactor ();
00523 if (r != 0)
00524 r->register_handler (this, proc->gethandle ());
00525 #endif
00526
00527 ++this->current_count_;
00528 return 0;
00529 }
00530
00531
00532
00533
00534 int
00535 ACE_Process_Manager::insert_proc (ACE_Process *proc,
00536 ACE_Event_Handler *event_handler)
00537 {
00538 ACE_TRACE ("ACE_Process_Manager::insert_proc");
00539
00540
00541
00542 if (this->find_proc (proc->getpid ()) != -1)
00543 return -1;
00544
00545 return this->append_proc (proc, event_handler);
00546 }
00547
00548
00549
00550 int
00551 ACE_Process_Manager::remove (pid_t pid)
00552 {
00553 ACE_TRACE ("ACE_Process_Manager::remove");
00554
00555 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00556
00557 ssize_t const i = this->find_proc (pid);
00558
00559 if (i != -1)
00560 return this->remove_proc (i);
00561
00562
00563 return -1;
00564 }
00565
00566
00567
00568 int
00569 ACE_Process_Manager::remove_proc (size_t i)
00570 {
00571 ACE_TRACE ("ACE_Process_Manager::remove_proc");
00572
00573
00574
00575
00576 if (this->process_table_[i].exit_notify_ != 0)
00577 {
00578 this->process_table_[i].exit_notify_->handle_close
00579 (this->process_table_[i].process_->gethandle(),
00580 0);
00581 this->process_table_[i].exit_notify_ = 0;
00582 }
00583
00584 #if defined (ACE_WIN32)
00585 ACE_Reactor * const r = this->reactor ();
00586 if (r != 0)
00587 r->remove_handler (this->process_table_[i].process_->gethandle (),
00588 ACE_Event_Handler::DONT_CALL);
00589 #endif
00590
00591 this->process_table_[i].process_->unmanage ();
00592
00593 this->process_table_[i].process_ = 0;
00594
00595 this->current_count_--;
00596
00597 if (this->current_count_ > 0)
00598
00599
00600 this->process_table_[i] =
00601 this->process_table_[this->current_count_];
00602
00603 return 0;
00604 }
00605
00606 int
00607 ACE_Process_Manager::terminate (pid_t pid)
00608 {
00609 ACE_TRACE ("ACE_Process_Manager::terminate");
00610
00611 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00612
00613
00614
00615 ssize_t const i = this->find_proc (pid);
00616
00617 if (i == -1)
00618
00619 return -1;
00620
00621 return ACE::terminate_process (pid);
00622 }
00623
00624 int
00625 ACE_Process_Manager::terminate (pid_t pid, int sig)
00626 {
00627 ACE_TRACE ("ACE_Process_Manager::terminate");
00628
00629 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00630
00631
00632
00633 ssize_t const i = this->find_proc (pid);
00634
00635 if (i == -1)
00636
00637 return -1;
00638
00639 return ACE_OS::kill (pid, sig);
00640 }
00641
00642
00643 int
00644 ACE_Process_Manager::set_scheduler (const ACE_Sched_Params & params,
00645 pid_t pid)
00646 {
00647 ACE_TRACE ("ACE_Process_Manager::set_scheduler");
00648
00649 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
00650 ace_mon, this->lock_, -1));
00651
00652
00653
00654 ssize_t const i = this->find_proc (pid);
00655
00656 if (i == -1)
00657
00658 return ACE_INVALID_PID;
00659
00660 return ACE_OS::sched_params (params, pid);
00661 }
00662
00663 int
00664 ACE_Process_Manager::set_scheduler_all (const ACE_Sched_Params & params)
00665 {
00666 ACE_TRACE ("ACE_Process_Manager::set_scheduler_all");
00667
00668 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
00669 ace_mon, this->lock_, -1));
00670
00671 for (size_t i = 0; i < this->current_count_; ++i)
00672 {
00673 pid_t const pid = this->process_table_[i].process_->getpid ();
00674 if (ACE_OS::sched_params (params, pid) != 0)
00675 return -1;
00676 }
00677 return 0;
00678 }
00679
00680
00681
00682
00683 ssize_t
00684 ACE_Process_Manager::find_proc (pid_t pid)
00685 {
00686 ACE_TRACE ("ACE_Process_Manager::find_proc");
00687
00688 for (size_t i = 0; i < this->current_count_; ++i)
00689 if (pid == this->process_table_[i].process_->getpid ())
00690 return i;
00691
00692 return -1;
00693 }
00694
00695 #if defined (ACE_WIN32)
00696
00697
00698
00699 ssize_t
00700 ACE_Process_Manager::find_proc (ACE_HANDLE h)
00701 {
00702 ACE_TRACE ("ACE_Process_Manager::find_proc");
00703
00704 for (size_t i = 0; i < this->current_count_; ++i)
00705 if (h == this->process_table_[i].process_->gethandle ())
00706 return i;
00707
00708 return -1;
00709 }
00710 #endif
00711
00712
00713
00714
00715 int
00716 ACE_Process_Manager::wait (const ACE_Time_Value &timeout)
00717 {
00718 ACE_TRACE ("ACE_Process_Manager::wait");
00719
00720 ACE_Time_Value until = timeout;
00721 ACE_Time_Value remaining = timeout;
00722
00723 if (until < ACE_Time_Value::max_time)
00724 until += ACE_OS::gettimeofday ();
00725
00726 while (this->current_count_ > 0)
00727 {
00728 pid_t const pid = this->wait (0, remaining);
00729
00730 if (pid == ACE_INVALID_PID)
00731 return -1;
00732 else if (pid == 0)
00733 break;
00734
00735 remaining = until < ACE_Time_Value::max_time
00736 ? until - ACE_OS::gettimeofday ()
00737 : ACE_Time_Value::max_time;
00738
00739 if (remaining <= ACE_Time_Value::zero)
00740 break;
00741
00742
00743 }
00744 return static_cast<int> (this->current_count_);
00745 }
00746
00747
00748
00749
00750
00751
00752
00753
00754 pid_t
00755 ACE_Process_Manager::wait (pid_t pid,
00756 ACE_exitcode *status)
00757 {
00758 ACE_TRACE ("ACE_Process_Manager::wait");
00759
00760 return this->wait (pid,
00761 ACE_Time_Value::max_time,
00762 status);
00763 }
00764
00765
00766
00767
00768
00769 pid_t
00770 ACE_Process_Manager::wait (pid_t pid,
00771 const ACE_Time_Value &timeout,
00772 ACE_exitcode *status)
00773 {
00774 ACE_TRACE ("ACE_Process_Manager::wait");
00775
00776 ACE_exitcode local_stat = 0;
00777 if (status == 0)
00778 status = &local_stat;
00779
00780 *status = 0;
00781
00782 ssize_t idx = -1;
00783 ACE_Process *proc = 0;
00784
00785 {
00786
00787 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00788
00789 if (pid != 0)
00790 {
00791 idx = this->find_proc (pid);
00792 if (idx == -1)
00793 return ACE_INVALID_PID;
00794 else
00795 proc = process_table_[idx].process_;
00796 }
00797
00798 }
00799 if (proc != 0)
00800 pid = proc->wait (timeout, status);
00801 else
00802 {
00803 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00804
00805 #if defined (ACE_WIN32)
00806 HANDLE *handles = 0;
00807
00808 ACE_NEW_RETURN (handles,
00809 HANDLE[this->current_count_],
00810 ACE_INVALID_PID);
00811
00812 for (size_t i = 0;
00813 i < this->current_count_;
00814 ++i)
00815 handles[i] =
00816 process_table_[i].process_->gethandle ();
00817
00818 DWORD handle_count = static_cast<DWORD> (this->current_count_);
00819 DWORD result = ::WaitForMultipleObjects (handle_count,
00820 handles,
00821 FALSE,
00822 timeout == ACE_Time_Value::max_time
00823 ? INFINITE
00824 : timeout.msec ());
00825 if (result == WAIT_FAILED)
00826 pid = ACE_INVALID_PID;
00827 else if (result == WAIT_TIMEOUT)
00828 pid = 0;
00829 else
00830 {
00831
00832
00833
00834
00835 # if defined (ghs) || defined (__MINGW32__) || (defined (_MSC_VER) && _MSC_VER >= 1300)
00836 ACE_ASSERT (result < WAIT_OBJECT_0 + this->current_count_);
00837 # else
00838 ACE_ASSERT (result >= WAIT_OBJECT_0
00839 && result < WAIT_OBJECT_0 + this->current_count_);
00840 # endif
00841
00842 idx = this->find_proc (handles[result - WAIT_OBJECT_0]);
00843
00844 if (idx != -1)
00845 {
00846 pid = process_table_[idx].process_->getpid ();
00847 result = ::GetExitCodeProcess (handles[result - WAIT_OBJECT_0],
00848 status);
00849 if (result == 0)
00850 {
00851
00852 this->remove_proc (idx);
00853 pid = ACE_INVALID_PID;
00854 }
00855 }
00856 else
00857 {
00858
00859
00860 delete [] handles;
00861 ACE_ERROR_RETURN ((LM_ERROR,
00862 ACE_TEXT ("Process removed")
00863 ACE_TEXT (" -- somebody's ignoring the lock!\n")),
00864 -1);
00865 }
00866 }
00867
00868 delete [] handles;
00869 #else
00870 if (timeout == ACE_Time_Value::max_time)
00871 pid = ACE_OS::waitpid (-1, status, 0);
00872 else if (timeout == ACE_Time_Value::zero)
00873 pid = ACE_OS::waitpid (-1, status, WNOHANG);
00874 else
00875 {
00876 # if defined (ACE_LACKS_UNIX_SIGNALS)
00877 pid = 0;
00878 ACE_Time_Value sleeptm (1);
00879 if (sleeptm > timeout)
00880 sleeptm = timeout;
00881 ACE_Time_Value tmo (timeout);
00882 for (ACE_Countdown_Time time_left (&tmo); tmo > ACE_Time_Value::zero ; time_left.update ())
00883 {
00884 pid = ACE_OS::waitpid (-1, status, WNOHANG);
00885 if (pid > 0 || pid == ACE_INVALID_PID)
00886 break;
00887
00888
00889
00890 ACE_OS::sleep (sleeptm);
00891 }
00892 # else
00893
00894
00895
00896
00897
00898 ACE_Sig_Action old_action;
00899 if (this->reactor () == 0)
00900 {
00901 ACE_Sig_Action do_sigchld ((ACE_SignalHandler)sigchld_nop);
00902 do_sigchld.register_action (SIGCHLD, &old_action);
00903 }
00904
00905 ACE_Time_Value tmo (timeout);
00906 for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
00907 {
00908 pid = ACE_OS::waitpid (-1, status, WNOHANG);
00909 # if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)
00910 if (pid > 0 || (pid == ACE_INVALID_PID && errno != EINTR))
00911 # else
00912 if (pid > 0 || pid == ACE_INVALID_PID)
00913 # endif
00914 break;
00915
00916
00917
00918
00919
00920
00921 if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
00922 continue;
00923
00924 pid = 0;
00925 break;
00926 }
00927
00928
00929 if (this->reactor () == 0)
00930 old_action.register_action (SIGCHLD);
00931 # endif
00932 }
00933 #endif
00934 }
00935
00936 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
00937 if (pid != ACE_INVALID_PID && pid != 0)
00938 {
00939
00940 idx = this->find_proc (pid);
00941 if (idx == -1)
00942 {
00943
00944 ACE_DEBUG ((LM_DEBUG,
00945 ACE_TEXT ("(%P|%t) oops, reaped unmanaged %d\n"),
00946 pid));
00947 return pid;
00948 }
00949 else
00950 proc = process_table_[idx].process_;
00951 if (proc != 0)
00952 ACE_ASSERT (pid == proc->getpid ());
00953
00954 this->notify_proc_handler (idx,
00955 *status);
00956 this->remove (pid);
00957 }
00958
00959 return pid;
00960 }
00961
00962
00963
00964 int
00965 ACE_Process_Manager::reap (pid_t pid,
00966 ACE_exitcode *stat_loc,
00967 int options)
00968 {
00969 ACE_TRACE ("ACE_Process_Manager::reap");
00970
00971 return this->wait (pid,
00972 (ACE_BIT_ENABLED (options, WNOHANG)
00973 ? ACE_Time_Value::zero
00974 : ACE_Time_Value::max_time),
00975 stat_loc);
00976 }
00977
00978
00979
00980
00981
00982 int
00983 ACE_Process_Manager::notify_proc_handler (size_t i,
00984 ACE_exitcode exit_code)
00985 {
00986 if (i < this->current_count_)
00987 {
00988 Process_Descriptor &proc_desc =
00989 this->process_table_[i];
00990
00991 proc_desc.process_->exit_code (exit_code);
00992
00993 if (proc_desc.exit_notify_ != 0)
00994 proc_desc.exit_notify_->handle_exit (proc_desc.process_);
00995 else if (this->default_exit_handler_ != 0
00996 && this->default_exit_handler_->handle_exit (proc_desc.process_) < 0)
00997 {
00998 this->default_exit_handler_->handle_close
00999 (ACE_INVALID_HANDLE,
01000 0);
01001 this->default_exit_handler_ = 0;
01002 }
01003 return 1;
01004 }
01005 else
01006 {
01007 ACE_DEBUG ((LM_DEBUG,
01008 ACE_TEXT ("(%P:%t|%T) ACE_Process_Manager::notify_proc_handler:")
01009 ACE_TEXT (" unknown/unmanaged process reaped\n")));
01010 return 0;
01011 }
01012 }
01013
01014 ACE_END_VERSIONED_NAMESPACE_DECL