summaryrefslogtreecommitdiff
path: root/ace/Process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ace/Process.cpp')
-rw-r--r--ace/Process.cpp134
1 files changed, 105 insertions, 29 deletions
diff --git a/ace/Process.cpp b/ace/Process.cpp
index a8d32cc33d8..c610e746f3d 100644
--- a/ace/Process.cpp
+++ b/ace/Process.cpp
@@ -1,6 +1,7 @@
// $Id$
#define ACE_BUILD_DLL
+#include "ace/OS.h"
#include "ace/Process.h"
#include "ace/ARGV.h"
#include "ace/SString.h"
@@ -9,16 +10,17 @@
#include "ace/Process.i"
#endif /* __ACE_INLINE__ */
-ACE_RCSID(ace, Process, "$Id$")
+ACE_RCSID (ace, Process, "$Id$")
ACE_Process::ACE_Process (void)
#if !defined (ACE_WIN32)
- : child_id_ (0)
+ : child_id_ (ACE_INVALID_PID)
#endif /* !defined (ACE_WIN32) */
{
#if defined (ACE_WIN32)
ACE_OS::memset ((void *) &this->process_info_,
- 0, sizeof this->process_info_);
+ 0,
+ sizeof this->process_info_);
#endif /* ACE_WIN32 */
}
@@ -47,27 +49,26 @@ ACE_Process::spawn (ACE_Process_Options &options)
options.startup_info (),
&this->process_info_);
- if (fork_result) // If success.
+ if (fork_result)
return this->getpid ();
else
- // CreateProcess failed.
- return -1;
+ return ACE_INVALID_PID;
#elif defined (CHORUS)
- // This only works if we <exec>. Chorus does not really support
- // <fork>.
+ // This only works if we exec. Chorus does not really support
+ // forking.
if (ACE_BIT_ENABLED (options.creation_flags (),
ACE_Process_Options::NO_EXEC))
- ACE_NOTSUP_RETURN (-1);
+ ACE_NOTSUP_RETURN (ACE_INVALID_PID);
// These are all currently unsupported.
if (options.get_stdin () != ACE_INVALID_HANDLE)
- ACE_NOTSUP_RETURN (-1);
+ ACE_NOTSUP_RETURN (ACE_INVALID_PID);
if (options.get_stdout () != ACE_INVALID_HANDLE)
- ACE_NOTSUP_RETURN (-1);
+ ACE_NOTSUP_RETURN (ACE_INVALID_PID);
if (options.get_stderr () != ACE_INVALID_HANDLE)
- ACE_NOTSUP_RETURN (-1);
+ ACE_NOTSUP_RETURN (ACE_INVALID_PID);
if (options.working_directory () != 0)
- ACE_NOTSUP_RETURN (-1);
+ ACE_NOTSUP_RETURN (ACE_INVALID_PID);
if (options.env_argv ()[0] == 0)
// command-line args
@@ -81,7 +82,7 @@ ACE_Process::spawn (ACE_Process_Options &options)
*user_env != 0;
user_env++)
if (ACE_OS::putenv (*user_env) != 0)
- return -1;
+ return ACE_INVALID_PID;
// Now the forked process has both inherited variables and the
// user's supplied variables.
@@ -95,6 +96,14 @@ ACE_Process::spawn (ACE_Process_Options &options)
this->child_id_ = ACE::fork (options.command_line_argv ()[0],
options.avoid_zombies ());
+ // If we're the child and the options specified a non-default
+ // process group, try to set our pgid to it. (This will allow
+ // Process_Manager to wait for Processes by process-group.)
+ if (options.getgroup () != ACE_INVALID_PID
+ && this->child_id_ == 0)
+ ACE_OS::setpgid (0,
+ options.getgroup ());
+
// If we're not supposed to exec, return the process id.
if (ACE_BIT_ENABLED (options.creation_flags (),
ACE_Process_Options::NO_EXEC))
@@ -104,9 +113,9 @@ ACE_Process::spawn (ACE_Process_Options &options)
{
case -1:
// Error.
- return -1;
+ return ACE_INVALID_PID;
case 0:
- // Child process.
+ // Child process...exec the
{
if (options.get_stdin () != ACE_INVALID_HANDLE
&& ACE_OS::dup2 (options.get_stdin (),
@@ -130,6 +139,7 @@ ACE_Process::spawn (ACE_Process_Options &options)
// process.
if (options.working_directory () != 0)
ACE_OS::chdir (options.working_directory ());
+ // Should check for error here!
// Child process executes the command.
int result = 0;
@@ -140,10 +150,10 @@ ACE_Process::spawn (ACE_Process_Options &options)
options.command_line_argv ());
else
{
-#if defined( ghs )
+#if defined (ghs)
// GreenHills 1.8.8 (for VxWorks 5.3.x) can't compile this
// code. Processes aren't supported on VxWorks anyways.
- ACE_NOTSUP_RETURN (-1);
+ ACE_NOTSUP_RETURN (ACE_INVALID_PID);
#else
// Add the new environment variables to the environment
// context of the context before doing an <execvp>.
@@ -151,7 +161,7 @@ ACE_Process::spawn (ACE_Process_Options &options)
*user_env != 0;
user_env++)
if (ACE_OS::putenv (*user_env) != 0)
- return -1;
+ return ACE_INVALID_PID;
// Now the forked process has both inherited variables and
// the user's supplied variables.
@@ -159,7 +169,6 @@ ACE_Process::spawn (ACE_Process_Options &options)
options.command_line_argv ());
#endif /* ghs */
}
-
if (result == -1)
{
// If the execv fails, this child needs to exit.
@@ -168,7 +177,7 @@ ACE_Process::spawn (ACE_Process_Options &options)
// catch this and figure out what went wrong.
ACE_OS::exit (errno);
}
-
+ // ... otherwise, this is never reached.
return 0;
}
default:
@@ -178,6 +187,71 @@ ACE_Process::spawn (ACE_Process_Options &options)
#endif /* ACE_WIN32 */
}
+pid_t
+ACE_Process::wait (const ACE_Time_Value &tv,
+ int *status)
+{
+#if defined (ACE_WIN32)
+ // Don't try to get the process exit status if wait failed so we can
+ // keep the original error code intact.
+ switch (::WaitForSingleObject (process_info_.hProcess,
+ tv.msec ()))
+ {
+ case WAIT_OBJECT_0:
+ if (status != 0)
+ // The error status of <GetExitCodeProcess> is nonetheless not
+ // tested because we don't know how to return the value.
+ ::GetExitCodeProcess (process_info_.hProcess,
+ (LPDWORD) status);
+ return 0;
+ case WAIT_TIMEOUT:
+ errno = ETIME;
+ return 0;
+ default:
+ ACE_OS::set_errno_to_last_error ();
+ return -1;
+ }
+#else /* ACE_WIN32 */
+ if (tv == ACE_Time_Value::zero)
+ ACE_OSCALL_RETURN (ACE_OS::waitpid (this->child_id_,
+ status,
+ WNOHANG),
+ int, ACE_INVALID_PID);
+
+ if (tv == ACE_Time_Value::max_time)
+ return this->wait (status);
+
+ ACE_Time_Value wait_until = ACE_OS::gettimeofday () + tv;
+
+ for (;;)
+ {
+ int result = ACE_OS::waitpid (this->getpid (),
+ status,
+ WNOHANG);
+ if (result != 0)
+ return result;
+
+ ACE_Sig_Set alarm_or_child;
+
+ alarm_or_child.sig_add (SIGALRM);
+ alarm_or_child.sig_add (SIGCHLD);
+
+ ACE_Time_Value time_left = wait_until - ACE_OS::gettimeofday ();
+
+ // If ACE_OS::ualarm doesn't have sub-second resolution:
+ time_left += ACE_Time_Value (0, 500000);
+ time_left.usec (0);
+
+ if (time_left <= ACE_Time_Value::zero)
+ return 0; // timeout
+
+ ACE_OS::ualarm (time_left);
+ if (ACE_OS::sigwait (alarm_or_child) == -1)
+ return ACE_INVALID_PID;
+ }
+#endif /* ACE_WIN32 */
+}
+
ACE_Process_Options::ACE_Process_Options (int ie,
int cobl,
int ebl,
@@ -208,7 +282,8 @@ ACE_Process_Options::ACE_Process_Options (int ie,
max_environ_argv_index_ (mea - 1),
#endif /* !ACE_HAS_WINCE */
command_line_argv_calculated_ (0),
- command_line_buf_ (0)
+ command_line_buf_ (0),
+ process_group_ (ACE_INVALID_PID)
{
ACE_NEW (command_line_buf_,
TCHAR[cobl]);
@@ -256,7 +331,8 @@ ACE_Process_Options::inherit_environment (void)
// Add the string to our env buffer.
if (this->setenv_i (existing_environment + slot, len) == -1)
{
- ACE_ERROR ((LM_ERROR, ASYS_TEXT ("%p.\n"),
+ ACE_ERROR ((LM_ERROR,
+ ASYS_TEXT ("%p.\n"),
ASYS_TEXT ("ACE_Process_Options::ACE_Process_Options")));
break;
}
@@ -434,27 +510,27 @@ ACE_Process_Options::set_handles (ACE_HANDLE std_in,
if (std_err == ACE_INVALID_HANDLE)
std_err = ACE_STDERR;
- if (!::DuplicateHandle (::GetCurrentProcess(),
+ if (!::DuplicateHandle (::GetCurrentProcess (),
std_in,
- ::GetCurrentProcess(),
+ ::GetCurrentProcess (),
&this->startup_info_.hStdInput,
NULL,
TRUE,
DUPLICATE_SAME_ACCESS))
return -1;
- if (!::DuplicateHandle (::GetCurrentProcess(),
+ if (!::DuplicateHandle (::GetCurrentProcess (),
std_out,
- ::GetCurrentProcess(),
+ ::GetCurrentProcess (),
&this->startup_info_.hStdOutput,
NULL,
TRUE,
DUPLICATE_SAME_ACCESS))
return -1;
- if (!::DuplicateHandle (::GetCurrentProcess(),
+ if (!::DuplicateHandle (::GetCurrentProcess (),
std_err,
- ::GetCurrentProcess(),
+ ::GetCurrentProcess (),
&this->startup_info_.hStdError,
NULL,
TRUE,