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