2 #include "ace/Process_Manager.h"
4 #if !defined (__ACE_INLINE__)
5 #include "ace/Process_Manager.inl"
6 #endif /* __ACE_INLINE__ */
9 #include "ace/Guard_T.h"
10 #include "ace/Process.h"
11 #include "ace/Signal.h"
12 #include "ace/Object_Manager.h"
13 #include "ace/Log_Category.h"
14 #include "ace/Reactor.h"
15 #include "ace/Countdown_Time.h"
16 #include "ace/OS_NS_sys_wait.h"
17 #include "ace/OS_NS_signal.h"
18 #include "ace/OS_NS_unistd.h"
19 #include "ace/OS_NS_sys_time.h"
20 #include "ace/os_include/os_typeinfo.h"
21 #include "ace/Truncate.h"
23 #if defined (ACE_HAS_SIG_C_FUNC)
25 ACE_Process_Manager_cleanup (void *instance
, void *arg
)
27 ACE_Process_Manager::cleanup (instance
, arg
);
29 #define ACE_PROCESS_MANAGER_CLEANUP_FUNCTION ACE_Process_Manager_cleanup
31 #define ACE_PROCESS_MANAGER_CLEANUP_FUNCTION ACE_Process_Manager::cleanup
34 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
37 ACE_Process_Manager::cleanup (void *, void *)
39 ACE_Process_Manager::close_singleton ();
42 // This function acts as a signal handler for SIGCHLD. We don't really
43 // want to do anything with the signal - it's just needed to interrupt
44 // a sleep. See wait() for more info.
45 #if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SIGNALS)
47 sigchld_nop (int, siginfo_t
*, ucontext_t
*)
51 #endif /* ACE_WIN32 */
54 ACE_ALLOC_HOOK_DEFINE(ACE_Process_Manager
)
56 // Singleton instance.
57 ACE_Process_Manager
*ACE_Process_Manager::instance_
= 0;
59 // Controls whether the Process_Manager is deleted when we shut down
60 // (we can only delete it safely if we created it!)
61 bool ACE_Process_Manager::delete_instance_
= false;
63 ACE_Process_Manager::Process_Descriptor::~Process_Descriptor ()
67 ACE_ALLOC_HOOK_DEFINE(ACE_Process_Manager::Process_Descriptor
)
70 ACE_Process_Manager::Process_Descriptor::dump () const
72 #if defined (ACE_HAS_DUMP)
73 ACE_TRACE ("ACE_Process_Manager::Process_Descriptor::dump");
75 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
77 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nproc_id_ = %d"),
78 this->process_
->getpid( )));
80 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
81 #endif /* ACE_HAS_DUMP */
85 ACE_Process_Manager::dump () const
87 #if defined (ACE_HAS_DUMP)
88 ACE_TRACE ("ACE_Process_Manager::dump");
90 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
92 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\nmax_process_table_size_ = %d"), this->max_process_table_size_
));
93 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\ncurrent_count_ = %d"), this->current_count_
));
95 for (size_t i
= 0; i
< this->current_count_
; i
++)
96 this->process_table_
[i
].dump ();
98 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
99 #endif /* ACE_HAS_DUMP */
102 ACE_Process_Manager::Process_Descriptor::Process_Descriptor ()
106 ACE_TRACE ("ACE_Process_Manager::Process_Descriptor::Process_Descriptor");
109 ACE_Process_Manager
*
110 ACE_Process_Manager::instance ()
112 ACE_TRACE ("ACE_Process_Manager::instance");
114 if (ACE_Process_Manager::instance_
== 0)
116 // Perform Double-Checked Locking Optimization.
117 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
,
118 *ACE_Static_Object_Lock::instance (), 0));
120 if (ACE_Process_Manager::instance_
== 0)
122 ACE_NEW_RETURN (ACE_Process_Manager::instance_
,
125 ACE_Process_Manager::delete_instance_
= true;
127 // Register with the Object_Manager so that the wrapper to
128 // delete the proactor will be called when Object_Manager is
130 ACE_Object_Manager::at_exit (ACE_Process_Manager::instance_
,
131 ACE_PROCESS_MANAGER_CLEANUP_FUNCTION
,
133 typeid (ACE_Process_Manager
).name ());
137 return ACE_Process_Manager::instance_
;
140 ACE_Process_Manager
*
141 ACE_Process_Manager::instance (ACE_Process_Manager
*tm
)
143 ACE_TRACE ("ACE_Process_Manager::instance");
144 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
,
145 *ACE_Static_Object_Lock::instance (), 0));
147 ACE_Process_Manager
*t
= ACE_Process_Manager::instance_
;
148 // We can't safely delete it since we don't know who created it!
149 ACE_Process_Manager::delete_instance_
= false;
151 // Register with the Object_Manager so that the wrapper to
152 // delete the proactor will be called when Object_Manager is
154 ACE_Object_Manager::at_exit (ACE_Process_Manager::instance_
,
155 ACE_PROCESS_MANAGER_CLEANUP_FUNCTION
,
157 typeid (*t
).name ());
159 ACE_Process_Manager::instance_
= tm
;
164 ACE_Process_Manager::close_singleton( )
166 ACE_TRACE ("ACE_Process_Manager::close_singleton");
168 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex
, ace_mon
,
169 *ACE_Static_Object_Lock::instance ()));
171 if (ACE_Process_Manager::delete_instance_
)
173 delete ACE_Process_Manager::instance_
;
174 ACE_Process_Manager::instance_
= 0;
175 ACE_Process_Manager::delete_instance_
= false;
180 ACE_Process_Manager::resize (size_t size
)
182 ACE_TRACE ("ACE_Process_Manager::resize");
184 if (size
<= this->max_process_table_size_
)
187 Process_Descriptor
*temp
= 0;
189 ACE_NEW_RETURN (temp
,
190 Process_Descriptor
[size
],
194 i
< this->current_count_
;
196 // Structure assignment.
197 temp
[i
] = this->process_table_
[i
];
199 this->max_process_table_size_
= size
;
201 delete [] this->process_table_
;
203 this->process_table_
= temp
;
207 // Create and initialize the table to keep track of the process pool.
209 ACE_Process_Manager::open (size_t size
, ACE_Reactor
*r
)
211 ACE_TRACE ("ACE_Process_Manager::open");
216 #if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SIGNALS)
217 // Register signal handler object.
218 if (r
->register_handler (SIGCHLD
, this) == -1)
220 #endif /* !defined(ACE_WIN32) */
223 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
, this->lock_
, -1));
225 if (this->max_process_table_size_
< size
)
230 // Initialize the synchronization variables.
231 ACE_Process_Manager::ACE_Process_Manager (size_t size
,
233 : ACE_Event_Handler (),
235 max_process_table_size_ (0),
237 default_exit_handler_ (0)
238 #if defined (ACE_HAS_THREADS)
240 #endif /* ACE_HAS_THREADS */
242 ACE_TRACE ("ACE_Process_Manager::ACE_Process_Manager");
244 if (this->open (size
, r
) == -1)
246 ACELIB_ERROR ((LM_ERROR
,
248 ACE_TEXT ("ACE_Process_Manager")));
252 // Close up and release all resources.
254 ACE_Process_Manager::close ()
256 ACE_TRACE ("ACE_Process_Manager::close");
258 if (this->reactor () != 0)
260 #if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SIGNALS)
261 this->reactor ()->remove_handler (SIGCHLD
, (ACE_Sig_Action
*) 0);
262 #endif /* !ACE_WIN32 */
266 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
, this->lock_
, -1));
268 if (this->process_table_
!= 0)
270 while (this->current_count_
> 0)
271 this->remove_proc (0);
273 delete [] this->process_table_
;
274 this->process_table_
= 0;
275 this->max_process_table_size_
= 0;
276 this->current_count_
= 0;
279 if (this->default_exit_handler_
!= 0)
280 this->default_exit_handler_
->handle_close (ACE_INVALID_HANDLE
,0);
281 this->default_exit_handler_
= 0;
286 ACE_Process_Manager::~ACE_Process_Manager ()
288 ACE_TRACE ("ACE_Process_Manager::~ACE_Process_Manager");
292 #if !defined (ACE_WIN32)
294 // This is called when the Reactor notices that a Process has exited.
295 // What has actually happened is a SIGCHLD invoked the <handle_signal>
296 // routine, which fooled the Reactor into thinking that this routine
297 // needed to be called. Since we don't know which Process exited, we
298 // must reap as many exit statuses as are immediately available.
300 ACE_Process_Manager::handle_input (ACE_HANDLE
)
302 ACE_TRACE ("ACE_Process_Manager::handle_input");
307 pid
= this->wait (0, ACE_Time_Value::zero
);
308 while (pid
!= 0 && pid
!= ACE_INVALID_PID
);
314 ACE_Process_Manager::handle_close (ACE_HANDLE
/* handle */,
315 ACE_Reactor_Mask close_mask
)
317 ACE_TRACE ("ACE_Process_Manager::handle_close");
318 if (close_mask
== ACE_Event_Handler::SIGNAL_MASK
)
320 // Reactor is telling us we're gone; don't unregister again later.
326 #endif /* !ACE_WIN32 */
328 // On Unix, this routine is called asynchronously when a SIGCHLD is
329 // received. We just tweak the reactor so that it'll call back our
330 // <handle_input> function, which allows us to handle Process exits
333 // On Win32, this routine is called synchronously, and is passed the
334 // HANDLE of the Process that exited, so we can do all our work here.
336 ACE_Process_Manager::handle_signal (int, siginfo_t
*si
, ucontext_t
*)
338 #if defined (ACE_WIN32)
339 ACE_HANDLE proc
= si
->si_handle_
;
340 ACE_exitcode status
= 0;
341 BOOL result
= ::GetExitCodeProcess (proc
, &status
);
344 if (status
!= STILL_ACTIVE
)
347 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
, lock_
, -1));
349 ssize_t
const i
= this->find_proc (proc
);
354 ? process_table_
[i
].process_
->getpid ()
357 this->notify_proc_handler (i
, status
);
358 this->remove_proc (i
);
360 return -1; // remove this HANDLE/Event_Handler combination
363 ACELIB_ERROR_RETURN ((LM_ERROR
,
364 ACE_TEXT ("Process still active")
365 ACE_TEXT (" -- shouldn't have been called yet!\n")),
366 0); // return 0 : stay registered
370 // <GetExitCodeProcess> failed.
371 ACELIB_ERROR_RETURN ((LM_ERROR
,
372 ACE_TEXT ("GetExitCodeProcess failed\n")),
373 -1); // return -1: unregister
375 #else /* !ACE_WIN32 */
377 return reactor ()->notify (this, ACE_Event_Handler::READ_MASK
);
378 #endif /* !ACE_WIN32 */
382 ACE_Process_Manager::register_handler (ACE_Event_Handler
*eh
,
385 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
, this->lock_
, -1));
387 if (pid
== ACE_INVALID_PID
)
389 if (this->default_exit_handler_
!= 0)
390 this->default_exit_handler_
->handle_close (ACE_INVALID_HANDLE
, 0);
391 this->default_exit_handler_
= eh
;
395 ssize_t
const i
= this->find_proc (pid
);
403 Process_Descriptor
&proc_desc
= this->process_table_
[i
];
405 if (proc_desc
.exit_notify_
!= 0)
406 proc_desc
.exit_notify_
->handle_close (ACE_INVALID_HANDLE
, 0);
407 proc_desc
.exit_notify_
= eh
;
411 // Create a new process.
413 ACE_Process_Manager::spawn (ACE_Process_Options
&options
,
414 ACE_Event_Handler
*event_handler
)
416 ACE_Process
*process
= 0;
417 ACE_NEW_RETURN (process
,
421 pid_t
const pid
= this->spawn (process
, options
, event_handler
);
422 if (pid
== ACE_INVALID_PID
|| pid
== 0)
428 // Create a new process.
430 ACE_Process_Manager::spawn (ACE_Process
*process
,
431 ACE_Process_Options
&options
,
432 ACE_Event_Handler
*event_handler
)
434 ACE_TRACE ("ACE_Process_Manager::spawn");
436 pid_t
const pid
= process
->spawn (options
);
438 // Only include the pid in the parent's table.
439 if (pid
== ACE_INVALID_PID
|| pid
== 0)
442 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
,
443 ace_mon
, this->lock_
, -1));
445 if (this->append_proc (process
, event_handler
) == -1)
446 // bad news: spawned, but not registered in table.
447 return ACE_INVALID_PID
;
452 // Create N new processs.
454 ACE_Process_Manager::spawn_n (size_t n
,
455 ACE_Process_Options
&options
,
457 ACE_Event_Handler
*event_handler
)
459 ACE_TRACE ("ACE_Process_Manager::spawn_n");
465 child_pids
[i
] = ACE_INVALID_PID
;
471 pid_t
const pid
= this->spawn (options
, event_handler
);
472 if (pid
== ACE_INVALID_PID
|| pid
== 0)
473 // We're in the child or something's gone wrong.
475 else if (child_pids
!= 0)
482 // Append a process into the pool (does not check for duplicates).
483 // Must be called with locks held.
485 ACE_Process_Manager::append_proc (ACE_Process
*proc
,
486 ACE_Event_Handler
*event_handler
)
488 ACE_TRACE ("ACE_Process_Manager::append_proc");
490 // Try to resize the array to twice its existing size (or the DEFAULT_SIZE,
491 // if there are no array entries) if we run out of space...
492 if (this->current_count_
>= this->max_process_table_size_
)
494 size_t new_size
= this->max_process_table_size_
* 2;
496 new_size
= ACE_Process_Manager::DEFAULT_SIZE
;
497 if (this->resize (new_size
) == -1)
501 Process_Descriptor
&proc_desc
=
502 this->process_table_
[this->current_count_
];
504 proc_desc
.process_
= proc
;
505 proc_desc
.exit_notify_
= event_handler
;
507 #if defined (ACE_WIN32)
508 // If we have a Reactor, then we're supposed to reap Processes
509 // automagically. Get a handle to this new Process and tell the
510 // Reactor we're interested in <handling_input> on it.
511 ACE_Reactor
* const r
= this->reactor ();
513 r
->register_handler (this, proc
->gethandle ());
514 #endif /* ACE_WIN32 */
516 ++this->current_count_
;
520 // Insert a process into the pool (checks for duplicates and doesn't
521 // allow them to be inserted twice).
523 ACE_Process_Manager::insert_proc (ACE_Process
*proc
,
524 ACE_Event_Handler
*event_handler
)
526 ACE_TRACE ("ACE_Process_Manager::insert_proc");
528 // Check for duplicates and bail out if they're already
530 if (this->find_proc (proc
->getpid ()) != -1)
533 return this->append_proc (proc
, event_handler
);
536 // Remove a process from the pool.
538 ACE_Process_Manager::remove (pid_t pid
)
540 ACE_TRACE ("ACE_Process_Manager::remove");
542 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
, this->lock_
, -1));
544 ssize_t
const i
= this->find_proc (pid
);
547 return this->remove_proc (i
);
549 // set "process not found" error
553 // Remove a process from the pool. Must be called with locks held.
555 ACE_Process_Manager::remove_proc (size_t i
)
557 ACE_TRACE ("ACE_Process_Manager::remove_proc");
559 // If there's an exit_notify_ <Event_Handler> for this pid, call its
560 // <handle_close> method.
562 if (this->process_table_
[i
].exit_notify_
!= 0)
564 this->process_table_
[i
].exit_notify_
->handle_close
565 (this->process_table_
[i
].process_
->gethandle(),
567 this->process_table_
[i
].exit_notify_
= 0;
570 #if defined (ACE_WIN32)
571 ACE_Reactor
* const r
= this->reactor ();
573 r
->remove_handler (this->process_table_
[i
].process_
->gethandle (),
574 ACE_Event_Handler::DONT_CALL
);
575 #endif /* ACE_WIN32 */
577 this->process_table_
[i
].process_
->unmanage ();
579 this->process_table_
[i
].process_
= 0;
581 this->current_count_
--;
583 if (this->current_count_
> 0)
584 // Compact the table by moving the last item into the slot vacated
585 // by the index being removed (this is a structure assignment).
586 this->process_table_
[i
] =
587 this->process_table_
[this->current_count_
];
593 ACE_Process_Manager::terminate (pid_t pid
)
595 ACE_TRACE ("ACE_Process_Manager::terminate");
597 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
, this->lock_
, -1));
599 // Check for duplicates and bail out if they're already
601 ssize_t
const i
= this->find_proc (pid
);
604 // set "no such process" error
607 return ACE::terminate_process (pid
);
611 ACE_Process_Manager::terminate (pid_t pid
, int sig
)
613 ACE_TRACE ("ACE_Process_Manager::terminate");
615 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
, this->lock_
, -1));
617 // Check for duplicates and bail out if they're already
619 ssize_t
const i
= this->find_proc (pid
);
622 // set "no such process" error
625 return ACE_OS::kill (pid
, sig
);
629 ACE_Process_Manager::set_scheduler (const ACE_Sched_Params
& params
,
632 ACE_TRACE ("ACE_Process_Manager::set_scheduler");
634 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
,
635 ace_mon
, this->lock_
, -1));
637 // Check to see if the process identified by the given pid is managed by
638 // this instance of ACE_Process_Manager.
639 ssize_t
const i
= this->find_proc (pid
);
642 // set "no such process" error
643 return ACE_INVALID_PID
;
645 return ACE_OS::sched_params (params
, pid
);
649 ACE_Process_Manager::set_scheduler_all (const ACE_Sched_Params
& params
)
651 ACE_TRACE ("ACE_Process_Manager::set_scheduler_all");
653 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
,
654 ace_mon
, this->lock_
, -1));
656 for (size_t i
= 0; i
< this->current_count_
; ++i
)
658 pid_t
const pid
= this->process_table_
[i
].process_
->getpid ();
659 if (ACE_OS::sched_params (params
, pid
) != 0)
665 // Locate the index in the table associated with <pid>. Must be
666 // called with the lock held.
668 ACE_Process_Manager::find_proc (pid_t pid
)
670 ACE_TRACE ("ACE_Process_Manager::find_proc");
672 for (size_t i
= 0; i
< this->current_count_
; ++i
)
674 if (pid
== this->process_table_
[i
].process_
->getpid ())
676 return ACE_Utils::truncate_cast
<ssize_t
> (i
);
683 #if defined (ACE_WIN32)
684 // Locate the index in the table associated with <h>. Must be
685 // called with the lock held.
687 ACE_Process_Manager::find_proc (ACE_HANDLE h
)
689 ACE_TRACE ("ACE_Process_Manager::find_proc");
691 for (size_t i
= 0; i
< this->current_count_
; ++i
)
693 if (h
== this->process_table_
[i
].process_
->gethandle ())
695 return ACE_Utils::truncate_cast
<ssize_t
> (i
);
701 #endif /* ACE_WIN32 */
703 // Wait for all the Processs to exit, or until @a timeout elapses.
704 // Returns the number of Processes remaining, or -1 on an error.
706 ACE_Process_Manager::wait (const ACE_Time_Value
&timeout
)
708 ACE_TRACE ("ACE_Process_Manager::wait");
710 ACE_Time_Value until
= timeout
;
711 ACE_Time_Value remaining
= timeout
;
713 if (until
< ACE_Time_Value::max_time
)
714 until
+= ACE_OS::gettimeofday ();
716 while (this->current_count_
> 0)
718 pid_t
const pid
= this->wait (0, remaining
);
720 if (pid
== ACE_INVALID_PID
) // wait() failed
722 else if (pid
== 0) // timeout
725 remaining
= until
< ACE_Time_Value::max_time
726 ? until
- ACE_OS::gettimeofday ()
727 : ACE_Time_Value::max_time
;
729 if (remaining
<= ACE_Time_Value::zero
)
732 // else Process terminated...wait for more...
734 return static_cast<int> (this->current_count_
);
737 // Collect a single child process' exit status. Store the exit code
738 // in *<stat_loc> if non-zero. Call the appropriate exit_notify. If
739 // <pid> == 0, wait for any of the Process_Manager's children (or as
740 // near as possible -- on Unix, we might accidentally get some other
741 // Process_Manager's Process, or an unmanaged Process, or a child
742 // process started by some other means.
744 ACE_Process_Manager::wait (pid_t pid
,
745 ACE_exitcode
*status
)
747 ACE_TRACE ("ACE_Process_Manager::wait");
749 return this->wait (pid
,
750 ACE_Time_Value::max_time
,
754 // Collect a single child processes' exit status, unless @a timeout
755 // elapses before the process exits. Same caveats about accidental
756 // Process reaping on Unix as above.
758 ACE_Process_Manager::wait (pid_t pid
,
759 const ACE_Time_Value
&timeout
,
760 ACE_exitcode
*status
)
762 ACE_TRACE ("ACE_Process_Manager::wait");
764 ACE_exitcode local_stat
= 0;
766 status
= &local_stat
;
771 ACE_Process
*proc
= 0;
774 // fake context after which the lock is released
775 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
, this->lock_
, -1));
779 idx
= this->find_proc (pid
);
781 return ACE_INVALID_PID
;
783 proc
= process_table_
[idx
].process_
;
788 pid
= proc
->wait (timeout
, status
);
791 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
, this->lock_
, -1));
792 // Wait for any Process spawned by this Process_Manager.
793 #if defined (ACE_WIN32)
796 ACE_NEW_RETURN (handles
,
797 HANDLE
[this->current_count_
],
801 i
< this->current_count_
;
804 process_table_
[i
].process_
->gethandle ();
806 DWORD handle_count
= static_cast<DWORD
> (this->current_count_
);
807 DWORD result
= ::WaitForMultipleObjects (handle_count
,
810 timeout
== ACE_Time_Value::max_time
813 if (result
== WAIT_FAILED
)
814 pid
= ACE_INVALID_PID
;
815 else if (result
== WAIT_TIMEOUT
)
819 // Green Hills produces a warning that result >=
820 // WAIT_OBJECT_0 is a pointless comparison because
821 // WAIT_OBJECT_0 is zero and DWORD is unsigned long, so this
822 // test is skipped for Green Hills. Same for mingw.
823 # if defined (__MINGW32__) || defined (_MSC_VER)
824 ACE_ASSERT (result
< WAIT_OBJECT_0
+ this->current_count_
);
826 ACE_ASSERT (result
>= WAIT_OBJECT_0
827 && result
< WAIT_OBJECT_0
+ this->current_count_
);
830 idx
= this->find_proc (handles
[result
- WAIT_OBJECT_0
]);
834 pid
= process_table_
[idx
].process_
->getpid ();
835 result
= ::GetExitCodeProcess (handles
[result
- WAIT_OBJECT_0
],
839 // <GetExitCodeProcess> failed!
840 this->remove_proc (idx
);
841 pid
= ACE_INVALID_PID
;
846 // uh oh...handle removed from process_table_, even though
847 // we're holding a lock!
849 ACELIB_ERROR_RETURN ((LM_ERROR
,
850 ACE_TEXT ("Process removed")
851 ACE_TEXT (" -- somebody's ignoring the lock!\n")),
857 #else /* !defined(ACE_WIN32) */
858 if (timeout
== ACE_Time_Value::max_time
)
859 pid
= ACE_OS::waitpid (-1, status
, 0);
860 else if (timeout
== ACE_Time_Value::zero
)
861 pid
= ACE_OS::waitpid (-1, status
, WNOHANG
);
864 # if defined (ACE_LACKS_UNIX_SIGNALS)
866 ACE_Time_Value
sleeptm (1); // 1 msec
867 if (sleeptm
> timeout
) // if sleeptime > waittime
869 ACE_Time_Value
tmo (timeout
); // Need one we can change
870 for (ACE_Countdown_Time
time_left (&tmo
); tmo
> ACE_Time_Value::zero
; time_left
.update ())
872 pid
= ACE_OS::waitpid (-1, status
, WNOHANG
);
873 if (pid
> 0 || pid
== ACE_INVALID_PID
)
874 break; // Got a child or an error - all done
876 // pid 0, nothing is ready yet, so wait.
877 // Do a (very) short sleep (only this thread sleeps).
878 ACE_OS::sleep (sleeptm
);
881 // Force generation of SIGCHLD, even though we don't want to
882 // catch it - just need it to interrupt the sleep below.
883 // If this object has a reactor set, assume it was given at
884 // open(), and there's already a SIGCHLD action set, so no
885 // action is needed here.
886 ACE_Sig_Action old_action
;
887 if (this->reactor () == 0)
889 ACE_Sig_Handler_Ex sigchld_nop_ptr
= sigchld_nop
;
890 ACE_Sig_Action
do_sigchld (reinterpret_cast<ACE_SignalHandler
> (reinterpret_cast<void*> (sigchld_nop_ptr
)));
891 do_sigchld
.register_action (SIGCHLD
, &old_action
);
894 ACE_Time_Value
tmo (timeout
); // Need one we can change
895 for (ACE_Countdown_Time
time_left (&tmo
); ; time_left
.update ())
897 pid
= ACE_OS::waitpid (-1, status
, WNOHANG
);
898 # if defined (ACE_VXWORKS)
899 if (pid
> 0 || (pid
== ACE_INVALID_PID
&& errno
!= EINTR
))
901 if (pid
> 0 || pid
== ACE_INVALID_PID
)
903 break; // Got a child or an error - all done
905 // pid 0, nothing is ready yet, so wait.
906 // Do a sleep (only this thread sleeps) til something
907 // happens. This relies on SIGCHLD interrupting the sleep.
908 // If SIGCHLD isn't delivered, we'll need to do something
909 // with sigaction to force it.
910 if (-1 == ACE_OS::sleep (tmo
) && errno
== EINTR
)
917 // Restore the previous SIGCHLD action if it was changed.
918 if (this->reactor () == 0)
919 old_action
.register_action (SIGCHLD
);
920 # endif /* !ACE_LACKS_UNIX_SIGNALS */
922 #endif /* !defined (ACE_WIN32) */
925 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
, this->lock_
, -1));
926 if (pid
!= ACE_INVALID_PID
&& pid
!= 0)
928 //we always need to get our id, because we could have been moved in the table meanwhile
929 idx
= this->find_proc (pid
);
932 // oops, reaped an unmanaged process!
933 ACELIB_DEBUG ((LM_DEBUG
,
934 ACE_TEXT ("(%P|%t) oops, reaped unmanaged %d\n"),
939 proc
= process_table_
[idx
].process_
;
941 ACE_ASSERT (pid
== proc
->getpid ());
943 this->notify_proc_handler (idx
,
951 // Notify either the process-specific handler or the generic handler.
952 // If process-specific, call handle_close on the handler. Returns 1
953 // if process found, 0 if not. Must be called with locks held.
955 ACE_Process_Manager::notify_proc_handler (size_t i
,
956 ACE_exitcode exit_code
)
958 if (i
< this->current_count_
)
960 Process_Descriptor
&proc_desc
=
961 this->process_table_
[i
];
963 proc_desc
.process_
->exit_code (exit_code
);
965 if (proc_desc
.exit_notify_
!= 0)
966 proc_desc
.exit_notify_
->handle_exit (proc_desc
.process_
);
967 else if (this->default_exit_handler_
!= 0
968 && this->default_exit_handler_
->handle_exit (proc_desc
.process_
) < 0)
970 this->default_exit_handler_
->handle_close (ACE_INVALID_HANDLE
, 0);
971 this->default_exit_handler_
= 0;
977 ACELIB_DEBUG ((LM_DEBUG
,
978 ACE_TEXT ("(%P:%t|%T) ACE_Process_Manager::notify_proc_handler:")
979 ACE_TEXT (" unknown/unmanaged process reaped\n")));
984 ACE_END_VERSIONED_NAMESPACE_DECL