Fixed typos
[ACE_TAO.git] / ACE / ace / Process.cpp
blobed29ffd5c5ad0a3b72592d49b3cf8ec374194570
1 #include "ace/Process.h"
3 #if !defined (__ACE_INLINE__)
4 #include "ace/Process.inl"
5 #endif /* __ACE_INLINE__ */
7 #include "ace/ARGV.h"
8 #include "ace/Auto_Ptr.h"
9 #include "ace/Signal.h"
10 #include "ace/SString.h"
11 #include "ace/Log_Category.h"
12 #include "ace/OS_NS_stdio.h"
13 #include "ace/OS_NS_stdlib.h"
14 #include "ace/OS_NS_sys_socket.h"
15 #include "ace/OS_NS_errno.h"
16 #include "ace/OS_NS_string.h"
17 #include "ace/OS_NS_unistd.h"
18 #include "ace/OS_NS_fcntl.h"
19 #include "ace/OS_Memory.h"
20 #include "ace/Countdown_Time.h"
21 #include "ace/Truncate.h"
22 #include "ace/Vector_T.h"
23 #include "ace/Tokenizer_T.h"
25 #if defined (ACE_VXWORKS) && defined (__RTP__)
26 # include <rtpLib.h>
27 # include <taskLib.h>
28 #endif
30 // This function acts as a signal handler for SIGCHLD. We don't really want
31 // to do anything with the signal - it's just needed to interrupt a sleep.
32 // See wait() for more info.
33 #if !defined (ACE_WIN32) && !defined(ACE_LACKS_UNIX_SIGNALS)
34 static void
35 sigchld_nop (int, siginfo_t *, ucontext_t *)
37 return;
39 #endif /* ACE_WIN32 */
42 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
44 ACE_Process::ACE_Process (void)
46 #if !defined (ACE_WIN32)
47 child_id_ (ACE_INVALID_PID),
48 #endif /* !defined (ACE_WIN32) */
49 exit_code_ (0)
51 #if defined (ACE_WIN32)
52 ACE_OS::memset ((void *) &this->process_info_,
54 sizeof this->process_info_);
55 #endif /* ACE_WIN32 */
58 ACE_Process::~ACE_Process (void)
60 #if defined (ACE_WIN32)
61 // Free resources allocated in kernel.
62 ACE_OS::close (this->process_info_.hThread);
63 ACE_OS::close (this->process_info_.hProcess);
64 #endif /* ACE_WIN32 */
65 // If any handles were duplicated for the child process and
66 // still not closed, get them now.
67 this->close_dup_handles ();
70 int
71 ACE_Process::prepare (ACE_Process_Options &)
73 return 0;
76 pid_t
77 ACE_Process::spawn (ACE_Process_Options &options)
79 if (this->prepare (options) < 0)
80 return ACE_INVALID_PID;
82 // Stash the passed/duped handle sets away in this object for later
83 // closing if needed or requested. At the same time, figure out which
84 // ones to include in command line options if that's needed below.
85 ACE_Handle_Set *set_p = 0;
86 if (options.dup_handles (this->dup_handles_))
87 set_p = &this->dup_handles_;
88 else if (options.passed_handles (this->handles_passed_))
89 set_p = &this->handles_passed_;
91 // If we are going to end up running a new program (i.e. Win32, or
92 // NO_EXEC option is set) then get any handles passed in the options,
93 // and tack them onto the command line with +H <handle> options,
94 // unless the command line runs out of space.
95 // Note that we're using the knowledge that all the options, argvs, etc.
96 // passed to the options are all sitting in the command_line_buf. Any
97 // call to get the argv then splits them out. So, regardless of the
98 // platform, tack them all onto the command line buf and take it
99 // from there.
100 if (set_p && !ACE_BIT_ENABLED (options.creation_flags (),
101 ACE_Process_Options::NO_EXEC))
103 size_t max_len = 0;
104 ACE_TCHAR *cmd_line_buf = options.command_line_buf (&max_len);
105 size_t curr_len = ACE_OS::strlen (cmd_line_buf);
106 ACE_Handle_Set_Iterator h_iter (*set_p);
107 // Because the length of the to-be-formatted +H option is not
108 // known, and we don't have a snprintf, guess at the space
109 // needed (20 chars), and use that as a limit.
110 for (ACE_HANDLE h = h_iter ();
111 h != ACE_INVALID_HANDLE && curr_len + 20 < max_len;
112 h = h_iter ())
114 #if defined (ACE_WIN32)
115 # if defined (ACE_WIN64)
116 // silence warnings coming from MinGW64 compilers
117 # if defined (__GNUC__)
118 # pragma GCC diagnostic push
119 # pragma GCC diagnostic ignored "-Wformat"
120 # pragma GCC diagnostic ignored "-Wformat-extra-args"
121 # endif /* __GNUC__ */
122 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
123 ACE_TEXT (" +H %I64p"),
125 # if defined (__GNUC__)
126 # pragma GCC diagnostic pop
127 # endif /* __GNUC__ */
128 # else
129 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
130 ACE_TEXT (" +H %p"),
132 # endif /* ACE_WIN64 */
133 #else
134 curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
135 ACE_TEXT (" +H %d"),
137 #endif /* ACE_WIN32 */
141 #if defined (ACE_HAS_WINCE)
142 // Note that WinCE does not have process name included in the command line as argv[0]
143 // like other OS environment. Therefore, it is user's whole responsibility to call
144 // 'ACE_Process_Options::process_name(const ACE_TCHAR *name)' to set the proper
145 // process name (the execution file name with path if needed).
146 BOOL fork_result =
147 ACE_TEXT_CreateProcess (options.process_name(),
148 options.command_line_buf(),
149 options.get_process_attributes(), // must be NULL in CE
150 options.get_thread_attributes(), // must be NULL in CE
151 options.handle_inheritance(), // must be false in CE
152 options.creation_flags(), // must be NULL in CE
153 options.env_buf(), // environment variables, must be NULL in CE
154 options.working_directory(), // must be NULL in CE
155 options.startup_info(), // must be NULL in CE
156 &this->process_info_);
158 if (fork_result)
160 parent (this->getpid ());
161 return this->getpid ();
163 return ACE_INVALID_PID;
165 #elif defined (ACE_WIN32)
166 void* env_buf = options.env_buf ();
167 DWORD flags = options.creation_flags ();
168 # if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
169 wchar_t* wenv_buf = 0;
170 if (options.use_unicode_environment ())
172 wenv_buf = this->convert_env_buffer (options.env_buf ());
173 env_buf = wenv_buf;
174 flags |= CREATE_UNICODE_ENVIRONMENT;
176 # endif
178 BOOL fork_result;
179 if (options.get_user_token () == ACE_INVALID_HANDLE)
181 fork_result = ACE_TEXT_CreateProcess (0,
182 options.command_line_buf (),
183 options.get_process_attributes (),
184 options.get_thread_attributes (),
185 options.handle_inheritance (),
186 flags,
187 env_buf, // environment variables
188 options.working_directory (),
189 options.startup_info (),
190 &this->process_info_);
192 else
194 fork_result = ACE_TEXT_CreateProcessAsUser (options.get_user_token (),
196 options.command_line_buf (),
197 options.get_process_attributes (),
198 options.get_thread_attributes (),
199 options.handle_inheritance (),
200 flags,
201 env_buf, // environment variables
202 options.working_directory (),
203 options.startup_info (),
204 &this->process_info_);
207 # if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
208 if (options.use_unicode_environment ())
209 delete wenv_buf;
210 # endif
212 if (fork_result)
214 parent (this->getpid ());
215 return this->getpid ();
217 return ACE_INVALID_PID;
219 #elif defined(ACE_OPENVMS)
220 if (ACE_BIT_ENABLED (options.creation_flags (),
221 ACE_Process_Options::NO_EXEC))
222 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
224 int saved_stdin = ACE_STDIN;
225 int saved_stdout = ACE_STDOUT;
226 int saved_stderr = ACE_STDERR;
227 // Save STD file descriptors and redirect
228 if (options.get_stdin () != ACE_INVALID_HANDLE) {
229 if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
230 ACE_OS::exit (errno);
231 if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
232 ACE_OS::exit (errno);
234 if (options.get_stdout () != ACE_INVALID_HANDLE) {
235 if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
236 ACE_OS::exit (errno);
237 if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
238 ACE_OS::exit (errno);
240 if (options.get_stderr () != ACE_INVALID_HANDLE) {
241 if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
242 ACE_OS::exit (errno);
243 if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
244 ACE_OS::exit (errno);
247 if (options.working_directory () != 0)
248 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
250 this->child_id_ = vfork();
251 if (this->child_id_ == 0) {
252 ACE_OS::execvp (options.process_name (),
253 options.command_line_argv ());
254 // something went wrong
255 this->child_id_ = ACE_INVALID_PID;
258 // restore STD file descriptors (if necessary)
259 if (options.get_stdin () != ACE_INVALID_HANDLE) {
260 if (saved_stdin == -1)
261 ACE_OS::close (ACE_STDIN);
262 else
263 ACE_OS::dup2 (saved_stdin, ACE_STDIN);
265 if (options.get_stdout () != ACE_INVALID_HANDLE) {
266 if (saved_stdout == -1)
267 ACE_OS::close (ACE_STDOUT);
268 else
269 ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
271 if (options.get_stderr () != ACE_INVALID_HANDLE) {
272 if (saved_stderr == -1)
273 ACE_OS::close (ACE_STDERR);
274 else
275 ACE_OS::dup2 (saved_stderr, ACE_STDERR);
278 return this->child_id_;
279 #elif defined (ACE_VXWORKS) && defined (__RTP__)
280 if (ACE_BIT_ENABLED (options.creation_flags (),
281 ACE_Process_Options::NO_EXEC))
282 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
284 if (options.working_directory () != 0)
285 ACE_NOTSUP_RETURN (ACE_INVALID_PID);
287 int saved_stdin = ACE_STDIN;
288 int saved_stdout = ACE_STDOUT;
289 int saved_stderr = ACE_STDERR;
290 // Save STD file descriptors and redirect
291 if (options.get_stdin () != ACE_INVALID_HANDLE) {
292 if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
293 ACE_OS::exit (errno);
294 if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
295 ACE_OS::exit (errno);
297 if (options.get_stdout () != ACE_INVALID_HANDLE) {
298 if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
299 ACE_OS::exit (errno);
300 if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
301 ACE_OS::exit (errno);
303 if (options.get_stderr () != ACE_INVALID_HANDLE) {
304 if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
305 ACE_OS::exit (errno);
306 if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
307 ACE_OS::exit (errno);
310 // Wide-char builds need narrow-char strings for commandline and
311 // environment variables.
312 # if defined (ACE_USES_WCHAR)
313 wchar_t * const *wargv = options.command_line_argv ();
314 size_t vcount, i;
315 for (vcount = 0; wargv[vcount] != 0; ++vcount)
317 char **procargv = new char *[vcount + 1]; // Need 0 at the end
318 procargv[vcount] = 0;
319 for (i = 0; i < vcount; ++i)
320 procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
322 char **procenv = 0;
323 if (options.inherit_environment ())
325 wargv = options.env_argv ();
326 for (vcount = 0; wargv[vcount] != 0; ++vcount)
328 procenv = new char *[vcount + 1]; // Need 0 at the end
329 procenv[vcount] = 0;
330 for (i = 0; i < vcount; ++i)
331 procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
333 # else
334 const char **procargv = const_cast<const char**> (options.command_line_argv ());
335 const char **procenv = const_cast<const char**> (options.env_argv ());
336 # endif /* ACE_USES_WCHAR */
338 this->child_id_ = ::rtpSpawn (procargv[0],
339 procargv,
340 procenv,
341 200, // priority
342 0x10000, // uStackSize
343 0, // options
344 VX_FP_TASK); // taskOptions
345 int my_errno_ = errno;
346 if (this->child_id_ == ERROR) {
347 // something went wrong
348 this->child_id_ = ACE_INVALID_PID;
351 # if defined (ACE_USES_WCHAR)
352 if (procenv)
353 delete [] procenv;
354 # endif /* ACE_USES_WCHAR */
356 // restore STD file descriptors (if necessary)
357 if (options.get_stdin () != ACE_INVALID_HANDLE) {
358 if (saved_stdin == -1)
359 ACE_OS::close (ACE_STDIN);
360 else
361 ACE_OS::dup2 (saved_stdin, ACE_STDIN);
363 if (options.get_stdout () != ACE_INVALID_HANDLE) {
364 if (saved_stdout == -1)
365 ACE_OS::close (ACE_STDOUT);
366 else
367 ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
369 if (options.get_stderr () != ACE_INVALID_HANDLE) {
370 if (saved_stderr == -1)
371 ACE_OS::close (ACE_STDERR);
372 else
373 ACE_OS::dup2 (saved_stderr, ACE_STDERR);
376 if (this->child_id_ == ACE_INVALID_PID)
378 errno = my_errno_;
381 return this->child_id_;
382 #else /* ACE_WIN32 */
383 // Fork the new process.
384 this->child_id_ = ACE::fork (options.process_name (),
385 options.avoid_zombies ());
387 if (this->child_id_ == 0)
389 # if !defined (ACE_LACKS_SETPGID)
390 // If we're the child and the options specified a non-default
391 // process group, try to set our pgid to it. This allows the
392 // <ACE_Process_Manager> to wait for processes by their
393 // process-group.
394 if (options.getgroup () != ACE_INVALID_PID
395 && ACE_OS::setpgid (0,
396 options.getgroup ()) < 0)
398 #if !defined (ACE_HAS_THREADS)
399 // We can't emit this log message because ACELIB_ERROR(), etc.
400 // will invoke async signal unsafe functions, which results
401 // in undefined behavior in threaded programs.
402 ACELIB_ERROR ((LM_ERROR,
403 ACE_TEXT ("%p.\n"),
404 ACE_TEXT ("ACE_Process::spawn: setpgid failed.")));
405 #endif
407 # endif /* ACE_LACKS_SETPGID */
409 # if !defined (ACE_LACKS_SETREGID)
410 if (options.getrgid () != (uid_t) -1
411 || options.getegid () != (uid_t) -1)
412 if (ACE_OS::setregid (options.getrgid (),
413 options.getegid ()) == -1)
415 #if !defined (ACE_HAS_THREADS)
416 // We can't emit this log message because ACELIB_ERROR(), etc.
417 // will invoke async signal unsafe functions, which results
418 // in undefined behavior in threaded programs.
419 ACELIB_ERROR ((LM_ERROR,
420 ACE_TEXT ("%p.\n"),
421 ACE_TEXT ("ACE_Process::spawn: setregid failed.")));
422 #endif
424 # endif /* ACE_LACKS_SETREGID */
426 # if !defined (ACE_LACKS_SETREUID)
427 // Set user and group id's.
428 if (options.getruid () != (uid_t) -1
429 || options.geteuid () != (uid_t) -1)
430 if (ACE_OS::setreuid (options.getruid (),
431 options.geteuid ()) == -1)
433 #if !defined (ACE_HAS_THREADS)
434 // We can't emit this log message because ACELIB_ERROR(), etc.
435 // will invoke async signal unsafe functions, which results
436 // in undefined behavior in threaded programs.
437 ACELIB_ERROR ((LM_ERROR,
438 ACE_TEXT ("%p.\n"),
439 ACE_TEXT ("ACE_Process::spawn: setreuid failed.")));
440 #endif
442 # endif /* ACE_LACKS_SETREUID */
444 this->child (ACE_OS::getppid ());
446 else if (this->child_id_ != -1)
447 this->parent (this->child_id_);
449 // If we're not supposed to exec, return the process id.
450 if (ACE_BIT_ENABLED (options.creation_flags (),
451 ACE_Process_Options::NO_EXEC))
452 return this->child_id_;
454 switch (this->child_id_)
456 case static_cast<pid_t>(-1):
457 // Error.
458 return ACE_INVALID_PID;
459 case 0:
460 // Child process...exec the
462 if (options.get_stdin () != ACE_INVALID_HANDLE
463 && ACE_OS::dup2 (options.get_stdin (),
464 ACE_STDIN) == -1)
465 ACE_OS::exit (errno);
466 else if (options.get_stdout () != ACE_INVALID_HANDLE
467 && ACE_OS::dup2 (options.get_stdout (),
468 ACE_STDOUT) == -1)
469 ACE_OS::exit (errno);
470 else if (options.get_stderr () != ACE_INVALID_HANDLE
471 && ACE_OS::dup2 (options.get_stderr (),
472 ACE_STDERR) == -1)
473 ACE_OS::exit (errno);
475 // close down unneeded descriptors
476 ACE_OS::close (options.get_stdin ());
477 ACE_OS::close (options.get_stdout ());
478 ACE_OS::close (options.get_stderr ());
479 if (!options.handle_inheritance ())
481 // Set close-on-exec for all FDs except standard handles
482 for (int i = ACE::max_handles () - 1; i >= 0; i--)
484 if (i == ACE_STDIN || i == ACE_STDOUT || i == ACE_STDERR)
485 continue;
486 ACE_OS::fcntl (i, F_SETFD, FD_CLOEXEC);
490 // If we must, set the working directory for the child
491 // process.
492 if (options.working_directory () != 0)
493 ACE_OS::chdir (options.working_directory ());
494 // Should check for error here!
496 // Child process executes the command.
497 int result = 0;
499 // Wide-char builds not on Windows need narrow-char strings for
500 // exec() and environment variables. Don't need to worry about
501 // releasing any of the converted string memory since this
502 // process will either exec() or exit() shortly.
503 # if defined (ACE_USES_WCHAR)
504 ACE_Wide_To_Ascii n_procname (options.process_name ());
505 const char *procname = n_procname.char_rep ();
507 wchar_t * const *wargv = options.command_line_argv ();
508 size_t vcount, i;
509 for (vcount = 0; wargv[vcount] != 0; ++vcount)
511 char **procargv = new char *[vcount + 1]; // Need 0 at the end
512 procargv[vcount] = 0;
513 for (i = 0; i < vcount; ++i)
514 procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
516 wargv = options.env_argv ();
517 for (vcount = 0; wargv[vcount] != 0; ++vcount)
519 char **procenv = new char *[vcount + 1]; // Need 0 at the end
520 procenv[vcount] = 0;
521 for (i = 0; i < vcount; ++i)
522 procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
523 # else
524 const char *procname = options.process_name ();
525 char *const *procargv = options.command_line_argv ();
526 char *const *procenv = options.env_argv ();
527 # endif /* ACE_USES_WCHAR */
529 if (options.inherit_environment ())
531 // Add the new environment variables to the environment
532 // context of the context before doing an <execvp>.
533 for (size_t i = 0; procenv[i] != 0; i++)
534 if (ACE_OS::putenv (procenv[i]) != 0)
535 return ACE_INVALID_PID;
537 // Now the forked process has both inherited variables and
538 // the user's supplied variables.
539 # ifdef ACE_LACKS_EXECVP
540 result = ACE_OS::execv (procname, procargv);
541 # else
542 result = ACE_OS::execvp (procname, procargv);
543 # endif
545 else
547 result = ACE_OS::execve (procname, procargv, procenv);
549 if (result == -1)
551 // If the execv fails, this child needs to exit.
553 // Exit with the errno so that the calling process can
554 // catch this and figure out what went wrong.
555 ACE_OS::_exit (errno);
557 // ... otherwise, this is never reached.
558 return 0;
560 default:
561 // Server process. The fork succeeded.
562 return this->child_id_;
564 #endif /* ACE_WIN32 */
567 void
568 ACE_Process::parent (pid_t)
570 // nothing to do
573 void
574 ACE_Process::child (pid_t)
576 // nothing to do
579 void
580 ACE_Process::unmanage (void)
582 // nothing to do
586 ACE_Process::running (void) const
588 #if defined (ACE_WIN32)
589 DWORD code;
591 BOOL result = ::GetExitCodeProcess (this->gethandle (),
592 &code);
593 return result && code == STILL_ACTIVE;
594 #else
595 if (ACE_INVALID_PID == this->getpid ())
596 return 0;
597 else
598 return ACE_OS::kill (this->getpid (),
599 0) == 0
600 || errno != ESRCH;
601 #endif /* ACE_WIN32 */
604 pid_t
605 ACE_Process::wait (const ACE_Time_Value &tv,
606 ACE_exitcode *status)
608 #if defined (ACE_WIN32)
609 // Don't try to get the process exit status if wait failed so we can
610 // keep the original error code intact.
611 switch (::WaitForSingleObject (process_info_.hProcess,
612 tv.msec ()))
614 case WAIT_OBJECT_0:
615 // The error status of <GetExitCodeProcess> is nonetheless not
616 // tested because we don't know how to return the value.
617 ::GetExitCodeProcess (process_info_.hProcess,
618 &this->exit_code_);
619 if (status != 0)
620 *status = this->exit_code_;
621 return this->getpid ();
622 case WAIT_TIMEOUT:
623 errno = ETIME;
624 return 0;
625 default:
626 ACE_OS::set_errno_to_last_error ();
627 return -1;
629 #elif defined(ACE_LACKS_UNIX_SIGNALS)
630 if (tv == ACE_Time_Value::zero)
632 pid_t retv =
633 ACE_OS::waitpid (this->child_id_,
634 &this->exit_code_,
635 WNOHANG);
636 if (status != 0)
637 *status = this->exit_code_;
639 return retv;
642 if (tv == ACE_Time_Value::max_time)
643 # if defined (ACE_VXWORKS)
645 pid_t retv;
646 while ((retv = this->wait (status)) == ACE_INVALID_PID && errno == EINTR) ;
647 return retv;
649 # else
650 return this->wait (status);
651 # endif
653 pid_t pid = 0;
654 ACE_Time_Value sleeptm (1); // 1 msec
655 if (sleeptm > tv) // if sleeptime > waittime
656 sleeptm = tv;
657 ACE_Time_Value tmo (tv); // Need one we can change
658 for (ACE_Countdown_Time time_left (&tmo); tmo > ACE_Time_Value::zero ; time_left.update ())
660 pid = ACE_OS::waitpid (this->getpid (),
661 &this->exit_code_,
662 WNOHANG);
663 if (status != 0)
664 *status = this->exit_code_;
666 if (pid > 0 || pid == ACE_INVALID_PID)
667 break; // Got a child or an error - all done
669 // pid 0, nothing is ready yet, so wait.
670 // Do a (very) short sleep (only this thread sleeps).
671 ACE_OS::sleep (sleeptm);
674 return pid;
675 #else /* !ACE_WIN32 && !ACE_LACKS_UNIX_SIGNALS */
676 if (tv == ACE_Time_Value::zero)
678 pid_t retv =
679 ACE_OS::waitpid (this->child_id_,
680 &this->exit_code_,
681 WNOHANG);
682 if (status != 0)
683 *status = this->exit_code_;
685 return retv;
688 if (tv == ACE_Time_Value::max_time)
689 return this->wait (status);
691 // Need to wait but limited to specified time.
692 // Force generation of SIGCHLD, even though we don't want to
693 // catch it - just need it to interrupt the sleep below.
694 // If this object has a reactor set, assume it was given at
695 // open(), and there's already a SIGCHLD action set, so no
696 // action is needed here.
697 ACE_Sig_Action old_action;
698 ACE_Sig_Action do_sigchld ((ACE_SignalHandler)sigchld_nop);
699 do_sigchld.register_action (SIGCHLD, &old_action);
701 pid_t pid;
702 ACE_Time_Value tmo (tv); // Need one we can change
703 for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
705 pid = ACE_OS::waitpid (this->getpid (),
706 &this->exit_code_,
707 WNOHANG);
708 if (status != 0)
709 *status = this->exit_code_;
711 if (pid > 0 || pid == ACE_INVALID_PID)
712 break; // Got a child or an error - all done
714 // pid 0, nothing is ready yet, so wait.
715 // Do a sleep (only this thread sleeps) til something
716 // happens. This relies on SIGCHLD interrupting the sleep.
717 // If SIGCHLD isn't delivered, we'll need to do something
718 // with sigaction to force it.
719 if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
720 continue;
721 // Timed out
722 pid = 0;
723 break;
726 // Restore the previous SIGCHLD action if it was changed.
727 old_action.register_action (SIGCHLD);
729 return pid;
730 #endif /* ACE_WIN32 */
733 void
734 ACE_Process::close_dup_handles (void)
736 if (this->dup_handles_.num_set () > 0)
738 ACE_Handle_Set_Iterator h_iter (this->dup_handles_);
739 for (ACE_HANDLE h = h_iter ();
740 h != ACE_INVALID_HANDLE;
741 h = h_iter ())
742 ACE_OS::closesocket (h);
743 this->dup_handles_.reset ();
745 return;
748 void
749 ACE_Process::close_passed_handles (void)
751 if (this->handles_passed_.num_set () > 0)
753 ACE_Handle_Set_Iterator h_iter (this->handles_passed_);
754 for (ACE_HANDLE h = h_iter ();
755 h != ACE_INVALID_HANDLE;
756 h = h_iter ())
757 ACE_OS::closesocket (h);
758 this->handles_passed_.reset ();
760 return;
763 #if defined (ACE_WIN32) && \
764 defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR) && \
765 !defined (ACE_HAS_WINCE)
766 wchar_t*
767 ACE_Process::convert_env_buffer (const char* env) const
769 // Total starts out at 1 due to the final block nul terminator
770 size_t total = 1;
772 // Convert each individual character string to the equivalent wide
773 // character string.
774 ACE_Vector<wchar_t*> buffer;
775 size_t start = 0;
776 size_t i = 0;
777 while (true)
779 if (env[i] == '\0')
781 // Convert the char string to wchar_t
782 wchar_t* str = ACE_Ascii_To_Wide::convert (env + start);
784 // Add the length of the string plus the nul terminator
785 total += ACE_OS::strlen (str) + 1;
787 // Save it and set up for the next string
788 buffer.push_back (str);
789 start = ++i;
790 if (env[start] == '\0')
791 break;
793 else
795 i += ACE_OS::strlen (env + i);
799 // Copy each string into the buffer leaving a nul terminator between
800 // each string and adding a second nul terminator at the end
801 start = 0;
802 wchar_t* wenv = new wchar_t[total];
803 size_t length = buffer.size ();
804 for (i = 0; i < length; ++i)
806 ACE_OS::strcpy(wenv + start, buffer[i]);
807 start += ACE_OS::strlen (buffer[i]) + 1;
808 delete [] buffer[i];
810 wenv[start] = 0;
811 return wenv;
813 #endif
815 ACE_Process_Options::ACE_Process_Options (bool inherit_environment,
816 size_t command_line_buf_len,
817 size_t env_buf_len,
818 size_t max_env_args,
819 size_t max_cmdline_args)
821 #if !defined (ACE_HAS_WINCE)
822 inherit_environment_ (inherit_environment),
823 #endif /* ACE_HAS_WINCE */
824 creation_flags_ (0),
825 avoid_zombies_ (0),
826 #if !defined (ACE_HAS_WINCE)
827 #if defined (ACE_WIN32)
828 environment_inherited_ (0),
829 process_attributes_ (0),
830 thread_attributes_ (0),
831 user_token_ (ACE_INVALID_HANDLE),
832 close_user_token_ (false),
833 #else /* ACE_WIN32 */
834 stdin_ (ACE_INVALID_HANDLE),
835 stdout_ (ACE_INVALID_HANDLE),
836 stderr_ (ACE_INVALID_HANDLE),
837 ruid_ ((uid_t) -1),
838 euid_ ((uid_t) -1),
839 rgid_ ((uid_t) -1),
840 egid_ ((uid_t) -1),
841 #endif /* ACE_WIN32 */
842 handle_inheritance_ (true),
843 set_handles_called_ (0),
844 environment_buf_index_ (0),
845 environment_argv_index_ (0),
846 environment_buf_ (0),
847 environment_buf_len_ (env_buf_len),
848 max_environment_args_ (max_env_args),
849 max_environ_argv_index_ (max_env_args - 1),
850 #endif /* !ACE_HAS_WINCE */
851 command_line_argv_calculated_ (false),
852 command_line_buf_ (0),
853 command_line_copy_ (0),
854 command_line_buf_len_ (command_line_buf_len),
855 max_command_line_args_ (max_cmdline_args),
856 command_line_argv_ (0),
857 process_group_ (ACE_INVALID_PID),
858 use_unicode_environment_ (false)
860 #if defined (ACE_HAS_ALLOC_HOOKS)
861 ACE_ALLOCATOR (command_line_buf_,
862 static_cast<ACE_TCHAR*>(ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR) * command_line_buf_len)));
863 #else
864 ACE_NEW (command_line_buf_,
865 ACE_TCHAR[command_line_buf_len]);
866 #endif /* ACE_HAS_ALLOC_HOOKS */
867 command_line_buf_[0] = '\0';
868 process_name_[0] = '\0';
870 #if defined (ACE_HAS_WINCE)
871 ACE_UNUSED_ARG(inherit_environment);
872 ACE_UNUSED_ARG(env_buf_len);
873 ACE_UNUSED_ARG(max_env_args);
874 #endif
876 #if !defined (ACE_HAS_WINCE)
877 working_directory_[0] = '\0';
878 #if defined (ACE_HAS_ALLOC_HOOKS)
879 ACE_ALLOCATOR (environment_buf_,
880 static_cast<ACE_TCHAR*>(ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR) * env_buf_len)));
881 #else
882 ACE_NEW (environment_buf_,
883 ACE_TCHAR[env_buf_len]);
884 #endif /* ACE_HAS_ALLOC_HOOKS */
885 #if defined (ACE_HAS_ALLOC_HOOKS)
886 ACE_ALLOCATOR (environment_argv_,
887 static_cast<ACE_TCHAR**>(ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR*) * max_env_args)));
888 #else
889 ACE_NEW (environment_argv_,
890 ACE_TCHAR *[max_env_args]);
891 #endif /* ACE_HAS_ALLOC_HOOKS */
892 environment_buf_[0] = '\0';
893 environment_argv_[0] = 0;
894 #if defined (ACE_WIN32)
895 ACE_OS::memset ((void *) &this->startup_info_,
897 sizeof this->startup_info_);
898 this->startup_info_.cb = sizeof this->startup_info_;
899 #endif /* ACE_WIN32 */
900 #endif /* !ACE_HAS_WINCE */
901 #if defined (ACE_HAS_ALLOC_HOOKS)
902 ACE_ALLOCATOR (command_line_argv_,
903 static_cast<ACE_TCHAR**>(ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR*) * max_cmdline_args)));
904 #else
905 ACE_NEW (command_line_argv_,
906 ACE_TCHAR *[max_cmdline_args]);
907 #endif /* ACE_HAS_ALLOC_HOOKS */
910 #if !defined (ACE_HAS_WINCE)
911 #if defined (ACE_WIN32)
912 void
913 ACE_Process_Options::inherit_environment (void)
915 // Ensure only once execution.
916 if (environment_inherited_)
917 return;
918 environment_inherited_ = 1;
920 // Get the existing environment.
921 ACE_TCHAR *existing_environment = 0;
922 #if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
923 WCHAR *existing_wide_env = 0;
924 ACE_Vector<char> temp_narrow_env;
925 if (this->use_unicode_environment_)
927 existing_wide_env = ::GetEnvironmentStringsW ();
928 for (WCHAR *iter = existing_wide_env; *iter; ++iter)
930 ACE_Wide_To_Ascii wta (iter);
931 size_t len = ACE_OS::strlen (wta.char_rep ());
932 size_t idx = temp_narrow_env.size ();
933 temp_narrow_env.resize (idx + len + 1, 0);
934 ACE_OS::strncpy (&temp_narrow_env[idx], wta.char_rep (), len);
935 iter += len;
937 temp_narrow_env.push_back (0);
938 existing_environment = &temp_narrow_env[0];
940 else
941 #endif
942 existing_environment = ACE_OS::getenvstrings ();
944 size_t slot = 0;
946 while (existing_environment[slot] != '\0')
948 size_t len = ACE_OS::strlen (existing_environment + slot);
950 // Add the string to our env buffer.
951 if (this->setenv_i (existing_environment + slot, len) == -1)
953 ACELIB_ERROR ((LM_ERROR,
954 ACE_TEXT ("%p.\n"),
955 ACE_TEXT ("ACE_Process_Options::ACE_Process_Options")));
956 break;
959 // Skip to the next word.
960 slot += len + 1;
963 #if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR)
964 if (this->use_unicode_environment_)
965 ::FreeEnvironmentStringsW (existing_wide_env);
966 else
967 #endif
968 ACE_TEXT_FreeEnvironmentStrings (existing_environment);
971 #else /* defined ACE_WIN32 */
973 ACE_TCHAR * const *
974 ACE_Process_Options::env_argv (void)
976 return environment_argv_;
979 #endif /* ACE_WIN32 */
982 ACE_Process_Options::setenv (ACE_TCHAR *envp[])
984 int i = 0;
985 while (envp[i])
987 if (this->setenv_i (envp[i],
988 ACE_OS::strlen (envp[i])) == -1)
989 return -1;
990 i++;
993 #if defined (ACE_WIN32)
994 if (inherit_environment_)
995 this->inherit_environment ();
996 #endif /* ACE_WIN32 */
998 return 0;
1001 #ifndef ACE_LACKS_VA_FUNCTIONS
1003 ACE_Process_Options::setenv (const ACE_TCHAR *format, ...)
1005 ACE_TCHAR stack_buf[DEFAULT_COMMAND_LINE_BUF_LEN];
1007 // Start varargs.
1008 va_list argp;
1009 va_start (argp, format);
1011 // Add the rest of the varargs.
1012 int status = ACE_OS::vsnprintf (stack_buf, DEFAULT_COMMAND_LINE_BUF_LEN,
1013 format, argp);
1014 // End varargs.
1015 va_end (argp);
1017 if (status == -1)
1018 return -1;
1020 // Append the string to are environment buffer.
1021 if (this->setenv_i (stack_buf,
1022 ACE_OS::strlen (stack_buf)) == -1)
1023 return -1;
1025 #if defined (ACE_WIN32)
1026 if (inherit_environment_)
1027 this->inherit_environment ();
1028 #endif /* ACE_WIN32 */
1030 return 0;
1034 ACE_Process_Options::setenv (const ACE_TCHAR *variable_name,
1035 const ACE_TCHAR *format, ...)
1037 // To address the potential buffer overflow,
1038 // we now allocate the buffer on heap with a variable size.
1039 size_t const buflen = ACE_OS::strlen (variable_name) + ACE_OS::strlen (format) + 2;
1040 ACE_TCHAR *newformat = 0;
1041 ACE_NEW_RETURN (newformat, ACE_TCHAR[buflen], -1);
1042 ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_newformat (newformat);
1044 # if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
1045 const ACE_TCHAR *fmt = ACE_TEXT ("%ls=%ls");
1046 # else
1047 const ACE_TCHAR *fmt = ACE_TEXT ("%s=%s");
1048 # endif
1050 // Add in the variable name.
1051 ACE_OS::snprintf (safe_newformat.get (), buflen, fmt,
1052 variable_name, format);
1054 // Add the rest of the varargs.
1055 size_t tmp_buflen = buflen;
1056 if (DEFAULT_COMMAND_LINE_BUF_LEN > buflen)
1058 tmp_buflen = DEFAULT_COMMAND_LINE_BUF_LEN;
1060 int retval = 0;
1062 ACE_TCHAR *stack_buf = 0;
1063 ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
1064 ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_stack_buf (stack_buf);
1068 // Must restart varargs on each time through this loop,
1069 va_list argp;
1070 va_start (argp, format);
1072 retval = ACE_OS::vsnprintf (safe_stack_buf.get (), tmp_buflen, safe_newformat.get (), argp);
1074 // End varargs.
1075 va_end (argp);
1077 if (retval > ACE_Utils::truncate_cast<int> (tmp_buflen))
1079 tmp_buflen *= 2;
1080 ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
1081 safe_stack_buf.reset (stack_buf);
1083 else
1084 break;
1086 while (1);
1088 if (retval == -1)
1090 // In case that vsnprintf is not supported,
1091 // e.g., LynxOS and VxWorks 5, we have to
1092 // fall back to vsprintf.
1093 if (errno == ENOTSUP)
1095 // ALERT: Since we have to use vsprintf here, there is still a chance that
1096 // the stack_buf overflows, i.e., the length of the resulting string
1097 // can still possibly go beyond the allocated stack_buf.
1098 va_list argp;
1099 va_start (argp, format);
1100 retval = ACE_OS::vsprintf (safe_stack_buf.get (), safe_newformat.get (), argp);
1101 va_end (argp);
1102 if (retval == -1)
1103 // vsprintf is failed.
1104 return -1;
1106 else
1107 // vsnprintf is failed.
1108 return -1;
1111 // Append the string to our environment buffer.
1112 if (this->setenv_i (safe_stack_buf.get (),
1113 ACE_OS::strlen (safe_stack_buf.get ())) == -1)
1114 return -1;
1116 #if defined (ACE_WIN32)
1117 if (inherit_environment_)
1118 this->inherit_environment ();
1119 #endif /* ACE_WIN32 */
1121 return 0;
1123 #endif // ACE_LACKS_VA_FUNCTIONS
1126 ACE_Process_Options::setenv_i (ACE_TCHAR *assignment,
1127 size_t len)
1129 // Add one for the null char.
1130 ++len;
1132 // If environment larger than allocated buffer return. Also check to
1133 // make sure we have enough room.
1134 if (environment_argv_index_ == max_environ_argv_index_
1135 || (len + environment_buf_index_) >= environment_buf_len_)
1136 return -1;
1138 // Copy the new environment string.
1139 ACE_OS::memcpy (environment_buf_ + environment_buf_index_,
1140 assignment,
1141 len * sizeof (ACE_TCHAR));
1143 // Update the argv array.
1144 environment_argv_[environment_argv_index_++] =
1145 environment_buf_ + environment_buf_index_;
1146 environment_argv_[environment_argv_index_] = 0;
1148 // Update our index.
1149 environment_buf_index_ += len;
1151 // Make sure the buffer is null-terminated.
1152 environment_buf_[environment_buf_index_] = '\0';
1153 return 0;
1157 ACE_Process_Options::set_handles (ACE_HANDLE std_in,
1158 ACE_HANDLE std_out,
1159 ACE_HANDLE std_err)
1161 this->set_handles_called_ = 1;
1162 #if defined (ACE_WIN32)
1164 // Tell the new process to use our std handles.
1165 this->startup_info_.dwFlags = STARTF_USESTDHANDLES;
1167 if (std_in == ACE_INVALID_HANDLE)
1168 std_in = ACE_STDIN;
1169 if (std_out == ACE_INVALID_HANDLE)
1170 std_out = ACE_STDOUT;
1171 if (std_err == ACE_INVALID_HANDLE)
1172 std_err = ACE_STDERR;
1174 // STD handles may have value 0 (not ACE_INVALID_HANDLE) if there is no such
1175 // handle in the process. This was observed to occur for stdin in console
1176 // processes that were launched from services. In this case we need to make
1177 // sure not to return -1 from setting std_in so that we can process std_out
1178 // and std_err.
1180 if (std_in)
1182 if (!::DuplicateHandle (::GetCurrentProcess (),
1183 std_in,
1184 ::GetCurrentProcess (),
1185 &this->startup_info_.hStdInput,
1187 TRUE,
1188 DUPLICATE_SAME_ACCESS))
1189 return -1;
1192 if (std_out)
1194 if (!::DuplicateHandle (::GetCurrentProcess (),
1195 std_out,
1196 ::GetCurrentProcess (),
1197 &this->startup_info_.hStdOutput,
1199 TRUE,
1200 DUPLICATE_SAME_ACCESS))
1201 return -1;
1204 if (std_err)
1206 if (!::DuplicateHandle (::GetCurrentProcess (),
1207 std_err,
1208 ::GetCurrentProcess (),
1209 &this->startup_info_.hStdError,
1211 TRUE,
1212 DUPLICATE_SAME_ACCESS))
1213 return -1;
1215 #else /* ACE_WIN32 */
1216 this->stdin_ = ACE_OS::dup (std_in);
1217 this->stdout_ = ACE_OS::dup (std_out);
1218 this->stderr_ = ACE_OS::dup (std_err);
1219 #endif /* ACE_WIN32 */
1221 return 0; // Success.
1225 void
1226 ACE_Process_Options::release_handles ()
1228 if (set_handles_called_)
1230 #if defined (ACE_WIN32)
1231 ACE_OS::close (startup_info_.hStdInput);
1232 ACE_OS::close (startup_info_.hStdOutput);
1233 ACE_OS::close (startup_info_.hStdError);
1234 #else /* ACE_WIN32 */
1235 ACE_OS::close (stdin_);
1236 ACE_OS::close (stdout_);
1237 ACE_OS::close (stderr_);
1238 #endif /* ACE_WIN32 */
1239 set_handles_called_ = 0;
1242 #endif /* !ACE_HAS_WINCE */
1245 ACE_Process_Options::~ACE_Process_Options (void)
1247 #if !defined (ACE_HAS_WINCE)
1248 release_handles();
1249 #if defined (ACE_HAS_ALLOC_HOOKS)
1250 ACE_Allocator::instance()->free(environment_buf_);
1251 ACE_Allocator::instance()->free(environment_argv_);
1252 #else
1253 delete [] environment_buf_;
1254 delete [] environment_argv_;
1255 #endif /* ACE_HAS_ALLOC_HOOKS */
1256 #endif /* !ACE_HAS_WINCE */
1257 #if defined (ACE_HAS_ALLOC_HOOKS)
1258 ACE_Allocator::instance()->free(command_line_buf_);
1259 #else
1260 delete [] command_line_buf_;
1261 #endif /* ACE_HAS_ALLOC_HOOKS */
1262 ACE::strdelete (command_line_copy_);
1263 #if defined (ACE_HAS_ALLOC_HOOKS)
1264 ACE_Allocator::instance()->free(command_line_argv_);
1265 #else
1266 delete [] command_line_argv_;
1267 #endif /* ACE_HAS_ALLOC_HOOKS */
1269 #if defined (ACE_WIN32)
1270 if (user_token_ != ACE_INVALID_HANDLE && close_user_token_)
1272 ::CloseHandle(user_token_);
1274 #endif /* ACE_WIN32 */
1278 ACE_Process_Options::command_line (const ACE_TCHAR *const argv[])
1280 int i = 0;
1282 if (argv[i])
1284 ACE_OS::strcat (command_line_buf_, argv[i]);
1286 while (argv[++i])
1288 // Check to see if the next argument will overflow the
1289 // command_line buffer.
1290 size_t const cur_len =
1291 ACE_OS::strlen (command_line_buf_)
1292 + ACE_OS::strlen (argv[i])
1293 + 2;
1295 if (cur_len > command_line_buf_len_)
1297 ACELIB_ERROR_RETURN ((LM_ERROR,
1298 ACE_TEXT ("ACE_Process:command_line: ")
1299 ACE_TEXT ("command line is ")
1300 ACE_TEXT ("longer than %d\n"),
1301 command_line_buf_len_),
1305 ACE_OS::strcat (command_line_buf_, ACE_TEXT (" "));
1306 ACE_OS::strcat (command_line_buf_, argv[i]);
1310 command_line_argv_calculated_ = false;
1311 return 0; // Success.
1314 #ifndef ACE_LACKS_VA_FUNCTIONS
1316 ACE_Process_Options::command_line (const ACE_TCHAR *format, ...)
1318 // Store all ... args in argp.
1319 va_list argp;
1320 va_start (argp, format);
1322 if (command_line_buf_len_ < 1)
1324 va_end (argp);
1325 return -1;
1328 ACE_OS::vsnprintf (command_line_buf_,
1329 command_line_buf_len_,
1330 format,
1331 argp);
1332 // Useless macro.
1333 va_end (argp);
1335 command_line_argv_calculated_ = false;
1336 return 0;
1339 #if defined (ACE_HAS_WCHAR) && !defined (ACE_HAS_WINCE)
1341 * @note Not available on Windows CE because it doesn't have a char version of
1342 * vsprintf.
1345 ACE_Process_Options::command_line (const ACE_ANTI_TCHAR *format, ...)
1347 ACE_ANTI_TCHAR *anti_clb = 0;
1348 ACE_NEW_RETURN (anti_clb,
1349 ACE_ANTI_TCHAR[this->command_line_buf_len_],
1350 -1);
1352 // Store all ... args in argp.
1353 va_list argp;
1354 va_start (argp, format);
1356 // sprintf the format and args into command_line_buf_.
1357 ACE_OS::vsnprintf (anti_clb, this->command_line_buf_len_, format, argp);
1359 // Useless macro.
1360 va_end (argp);
1362 ACE_OS::strcpy (this->command_line_buf_,
1363 ACE_TEXT_ANTI_TO_TCHAR (anti_clb));
1365 delete [] anti_clb;
1367 command_line_argv_calculated_ = false;
1368 return 0;
1370 #endif /* ACE_HAS_WCHAR && !ACE_HAS_WINCE */
1371 #endif // ACE_LACKS_VA_FUNCTIONS
1373 ACE_TCHAR *
1374 ACE_Process_Options::env_buf (void)
1376 #if !defined (ACE_HAS_WINCE)
1377 if (environment_buf_[0] == '\0')
1378 return 0;
1379 else
1380 return environment_buf_;
1381 #else
1382 return 0;
1383 #endif /* !ACE_HAS_WINCE */
1386 ACE_TCHAR * const *
1387 ACE_Process_Options::command_line_argv (void)
1389 if (!command_line_argv_calculated_)
1391 command_line_argv_calculated_ = true;
1393 // We need to free up any previous allocated memory first.
1394 ACE::strdelete (command_line_copy_);
1396 // We need to make a dynamically allocated copy here since
1397 // ACE_Tokenizer modifies its arguments.
1398 command_line_copy_ = ACE::strnew (command_line_buf_);
1399 // This tokenizer will replace all spaces with end-of-string
1400 // characters and will preserve text between "" and '' pairs.
1401 ACE_Tokenizer parser (command_line_copy_);
1402 parser.delimiter_replace (' ', '\0');
1403 parser.preserve_designators ('\"', '\"'); // "
1404 parser.preserve_designators ('\'', '\'');
1406 unsigned int x = 0;
1408 command_line_argv_[x] = parser.next ();
1409 while (command_line_argv_[x] != 0
1410 // subtract one for the ending zero.
1411 && ++x < max_command_line_args_ - 1);
1413 command_line_argv_[x] = 0;
1416 return command_line_argv_;
1419 // Cause the specified handle to be passed to a child process
1420 // when it's spawned.
1422 ACE_Process_Options::pass_handle (ACE_HANDLE h)
1424 #if defined (ACE_HAS_WINCE)
1425 ACE_NOTSUP_RETURN (-1);
1426 #else
1427 this->handles_passed_.set_bit (h);
1428 return 0;
1429 #endif /* ACE_HAS_WINCE */
1432 // Get a copy of the handles the ACE_Process_Options duplicated
1433 // for the spawned process.
1435 ACE_Process_Options::dup_handles (ACE_Handle_Set &set) const
1437 if (this->dup_handles_.num_set () == 0)
1438 return 0;
1439 set.reset ();
1440 set = this->dup_handles_;
1441 return 1;
1444 // Get a copy of the handles passed to the spawned process. This
1445 // will be the set of handles previously passed to @arg pass_handle().
1447 ACE_Process_Options::passed_handles (ACE_Handle_Set &set) const
1449 if (this->handles_passed_.num_set () == 0)
1450 return 0;
1451 set.reset ();
1452 set = this->handles_passed_;
1453 return 1;
1456 ACE_Managed_Process::~ACE_Managed_Process (void)
1460 ACE_ALLOC_HOOK_DEFINE(ACE_Managed_Process)
1462 void
1463 ACE_Managed_Process::unmanage (void)
1465 delete this;
1468 #if defined (ACE_WIN32)
1469 void
1470 ACE_Process_Options::set_user_token (HANDLE token, bool close_token)
1472 if (user_token_ != ACE_INVALID_HANDLE && close_user_token_)
1474 ::CloseHandle(user_token_);
1477 user_token_ = token;
1478 close_user_token_ = close_token;
1480 #endif /* ACE_WIN32 */
1482 ACE_END_VERSIONED_NAMESPACE_DECL