ACE_Process Class Reference

Process. More...

#include <Process.h>

Inheritance diagram for ACE_Process:

Inheritance graph
[legend]
Collaboration diagram for ACE_Process:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 ACE_Process (void)
 Default construction. Must use <ACE_Process::spawn> to start.

virtual ~ACE_Process (void)
 Destructor.

virtual int prepare (ACE_Process_Options &options)
virtual pid_t spawn (ACE_Process_Options &options)
virtual void parent (pid_t child)
virtual void child (pid_t parent)
virtual void unmanage (void)
pid_t wait (ACE_exitcode *status=0, int wait_options=0)
pid_t wait (const ACE_Time_Value &tv, ACE_exitcode *status=0)
int kill (int signum=SIGINT)
int terminate (void)
pid_t getpid (void) const
 Return the process id of the new child process.

ACE_HANDLE gethandle (void) const
 Return the handle of the process, if it has one.

int running (void) const
 Return 1 if running; 0 otherwise.

ACE_exitcode exit_code (void) const
int return_value (void) const
void close_dup_handles (void)
void close_passed_handles (void)
PROCESS_INFORMATION process_info (void)

Protected Member Functions

void exit_code (ACE_exitcode code)

Protected Attributes

PROCESS_INFORMATION process_info_
ACE_exitcode exit_code_
ACE_Handle_Set handles_passed_
 Set of handles that were passed to the child process.

ACE_Handle_Set dup_handles_
 Handle duplicates made for the child process.


Private Member Functions

 ACE_Process (const ACE_Process &)
void operator= (const ACE_Process &)

Friends

class ACE_Process_Manager

Detailed Description

Process.

A Portable encapsulation for creating new processes. Notice that on UNIX platforms, if the is used, the is using the system call. It means that the should include a full path to the program file ( does not search the PATH). If is not used then, the is using the which searches for the program file in the PATH variable.

Definition at line 447 of file Process.h.


Constructor & Destructor Documentation

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_Process::ACE_Process void   ) 
 

Default construction. Must use <ACE_Process::spawn> to start.

Definition at line 45 of file Process.cpp.

References ACE_INVALID_PID, and ACE_OS::memset().

00046   :
00047 #if !defined (ACE_WIN32)
00048   child_id_ (ACE_INVALID_PID),
00049 #endif /* !defined (ACE_WIN32) */
00050   exit_code_ (0)
00051 {
00052 #if defined (ACE_WIN32)
00053   ACE_OS::memset ((void *) &this->process_info_,
00054                   0,
00055                   sizeof this->process_info_);
00056 #endif /* ACE_WIN32 */
00057 }

ACE_Process::~ACE_Process void   )  [virtual]
 

Destructor.

Definition at line 59 of file Process.cpp.

References ACE_OS::close(), and close_dup_handles().

00060 {
00061 #if defined (ACE_WIN32)
00062   // Free resources allocated in kernel.
00063   ACE_OS::close (this->process_info_.hThread);
00064   ACE_OS::close (this->process_info_.hProcess);
00065 #endif /* ACE_WIN32 */
00066   // If any handles were duplicated for the child process and
00067   // still not closed, get them now.
00068   this->close_dup_handles ();
00069 }

ACE_Process::ACE_Process const ACE_Process  )  [private]
 


Member Function Documentation

void ACE_Process::child pid_t  parent  )  [virtual]
 

Called just after <ACE_OS::fork> in the child's context. The default does nothing. This function is *not* called on Win32 because the process-creation scheme does not allow it.

Definition at line 504 of file Process.cpp.

References pid_t.

Referenced by spawn().

00505 {
00506   // nothing to do
00507 }

void ACE_Process::close_dup_handles void   ) 
 

Close all the handles in the set obtained from the

Definition at line 664 of file Process.cpp.

References ACE_OS::closesocket(), ACE_Handle_Set::num_set(), and ACE_Handle_Set::reset().

Referenced by ~ACE_Process().

00665 {
00666   if (this->dup_handles_.num_set () > 0)
00667     {
00668       ACE_Handle_Set_Iterator h_iter (this->dup_handles_);
00669       for (ACE_HANDLE h = h_iter ();
00670            h != ACE_INVALID_HANDLE;
00671            h = h_iter ())
00672         ACE_OS::closesocket (h);
00673       this->dup_handles_.reset ();
00674     }
00675   return;
00676 }

void ACE_Process::close_passed_handles void   ) 
 

Close all the handles in the set obtained from the

Definition at line 679 of file Process.cpp.

References ACE_OS::closesocket(), ACE_Handle_Set::num_set(), and ACE_Handle_Set::reset().

00680 {
00681   if (this->handles_passed_.num_set () > 0)
00682     {
00683       ACE_Handle_Set_Iterator h_iter (this->handles_passed_);
00684       for (ACE_HANDLE h = h_iter ();
00685            h != ACE_INVALID_HANDLE;
00686            h = h_iter ())
00687         ACE_OS::closesocket (h);
00688       this->handles_passed_.reset ();
00689     }
00690   return;
00691 }

ACE_INLINE void ACE_Process::exit_code ACE_exitcode  code  )  [protected]
 

Set this process' . ACE_Process_Manager uses this method to set the after successfully waiting for this process to exit.

Definition at line 96 of file Process.inl.

References ACE_exitcode, and exit_code_.

00097 {
00098   this->exit_code_ = code;
00099 }

ACE_INLINE ACE_exitcode ACE_Process::exit_code void   )  const
 

Return the Process' exit code. This method returns the raw exit status returned from system APIs (such as or ). This value is system dependent.

Definition at line 90 of file Process.inl.

References exit_code_.

Referenced by ACE_Process_Manager::notify_proc_handler().

00091 {
00092   return this->exit_code_;
00093 }

ACE_INLINE ACE_HANDLE ACE_Process::gethandle void   )  const
 

Return the handle of the process, if it has one.

Definition at line 23 of file Process.inl.

References process_info_.

Referenced by ACE_Process_Manager::append_proc(), ACE_Process_Manager::find_proc(), ACE_Process_Manager::remove_proc(), running(), and ACE_Process_Manager::wait().

00024 {
00025 #if defined (ACE_WIN32)
00026   return process_info_.hProcess;
00027 #else
00028   return ACE_HANDLE (child_id_);
00029 #endif /* ACE_WIN32 */
00030 }

ACE_INLINE pid_t ACE_Process::getpid void   )  const
 

Return the process id of the new child process.

Definition at line 33 of file Process.inl.

Referenced by ACE_Process_Manager::find_proc(), ACE_Process_Manager::handle_signal(), ACE_Process_Manager::insert_proc(), kill(), running(), ACE_Process_Manager::set_scheduler_all(), spawn(), terminate(), ACE_Process_Manager::wait(), and wait().

00035 {
00036 #if defined (ACE_WIN32)
00037   return process_info_.dwProcessId;
00038 #else /* ACE_WIN32 */
00039   return child_id_;
00040 #endif /* ACE_WIN32 */
00041 }

ACE_INLINE int ACE_Process::kill int  signum = SIGINT  ) 
 

Send the process a signal. This is only portable to operating systems that support signals, such as UNIX/POSIX.

Definition at line 62 of file Process.inl.

References getpid(), and ACE_OS::kill().

00063 {
00064   if (this->getpid () != -1)
00065     return ACE_OS::kill (this->getpid (), signum);
00066   else
00067     return -1;
00068 }

void ACE_Process::operator= const ACE_Process  )  [private]
 

void ACE_Process::parent pid_t  child  )  [virtual]
 

Called just after <ACE_OS::fork> in the parent's context, if the succeeds. The default is to do nothing.

Definition at line 498 of file Process.cpp.

References pid_t.

Referenced by spawn().

00499 {
00500   // nothing to do
00501 }

int ACE_Process::prepare ACE_Process_Options options  )  [virtual]
 

Called just before <ACE_OS::fork> in the . If this returns non-zero, the is aborted (and returns ACE_INVALID_PID). The default simply returns zero.

Definition at line 72 of file Process.cpp.

Referenced by spawn().

00073 {
00074   return 0;
00075 }

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE PROCESS_INFORMATION ACE_Process::process_info void   ) 
 

Definition at line 16 of file Process.inl.

References process_info_.

00017 {
00018   return process_info_;
00019 }

ACE_INLINE int ACE_Process::return_value void   )  const
 

Return the Process' return value. This method returns the actual return value that a child process returns or s.

Definition at line 80 of file Process.inl.

References exit_code_, and WEXITSTATUS.

00081 {
00082 #if defined (ACE_WIN32)
00083   return this->exit_code_;
00084 #else
00085   return WEXITSTATUS (this->exit_code_);
00086 #endif /* ACE_WIN32 */
00087 }

int ACE_Process::running void   )  const
 

Return 1 if running; 0 otherwise.

Definition at line 516 of file Process.cpp.

References ACE_INVALID_PID, gethandle(), getpid(), and ACE_OS::kill().

00517 {
00518 #if defined (ACE_WIN32)
00519     DWORD code;
00520 
00521     BOOL result = ::GetExitCodeProcess (this->gethandle (),
00522                                         &code);
00523     return result && code == STILL_ACTIVE;
00524 #else
00525   if (ACE_INVALID_PID == this->getpid ())
00526     return 0;
00527   else
00528     return ACE_OS::kill (this->getpid (),
00529                          0) == 0
00530       || errno != ESRCH;
00531 #endif /* ACE_WIN32 */
00532 }

pid_t ACE_Process::spawn ACE_Process_Options options  )  [virtual]
 

Launch a new process as described by options. On success, returns 1 if the option avoid_zombies is set, else returns the process id of the newly spawned child. Returns -1 on failure. This will be fixed in the future versions of ACE when the process id of the child will be returned regardless of the option.

Definition at line 78 of file Process.cpp.

References ACE_OS::_exit(), ACE_BIT_ENABLED, ACE_ERROR, ACE_INVALID_PID, ACE_NOTSUP_RETURN, ACE_STDERR, ACE_STDIN, ACE_STDOUT, ACE_TCHAR, ACE_TEXT, ACE_TEXT_CreateProcess, ACE_Process_Options::avoid_zombies(), ACE_Wide_To_Ascii::char_rep(), ACE_OS::chdir(), child(), ACE_OS::close(), ACE_Process_Options::command_line_argv(), ACE_Process_Options::command_line_buf(), ACE_Wide_To_Ascii::convert(), ACE_Process_Options::creation_flags(), ACE_OS::dup(), ACE_OS::dup2(), ACE_Process_Options::dup_handles(), ACE_Process_Options::env_buf(), ACE_OS::execve(), ACE_OS::execvp(), ACE_OS::exit(), ACE::fork(), ACE_Process_Options::get_process_attributes(), ACE_Process_Options::get_thread_attributes(), ACE_Process_Options::getgroup(), getpid(), ACE_Process_Options::handle_inheritence(), ACE_Process_Options::inherit_environment(), LM_ERROR, parent(), ACE_Process_Options::passed_handles(), prepare(), process_info_, ACE_Process_Options::process_name(), ACE_OS::putenv(), ACE_OS::setpgid(), ACE_OS::setregid(), ACE_OS::setreuid(), ACE_OS::sprintf(), ACE_Process_Options::startup_info(), ACE_OS::strlen(), uid_t, and ACE_Process_Options::working_directory().

Referenced by ACE_Process_Manager::spawn().

00079 {
00080   if (prepare (options) < 0)
00081     return ACE_INVALID_PID;
00082 
00083   // Stash the passed/duped handle sets away in this object for later
00084   // closing if needed or requested. At the same time, figure out which
00085   // ones to include in command line options if that's needed below.
00086   ACE_Handle_Set *set_p = 0;
00087   if (options.dup_handles (this->dup_handles_))
00088     set_p = &this->dup_handles_;
00089   else if (options.passed_handles (this->handles_passed_))
00090     set_p = &this->handles_passed_;
00091 
00092   // If we are going to end up running a new program (i.e. Win32, or
00093   // NO_EXEC option is set) then get any handles passed in the options,
00094   // and tack them onto the command line with +H <handle> options,
00095   // unless the command line runs out of space.
00096   // Note that we're using the knowledge that all the options, argvs, etc.
00097   // passed to the options are all sitting in the command_line_buf. Any
00098   // call to get the argv then splits them out. So, regardless of the
00099   // platform, tack them all onto the command line buf and take it
00100   // from there.
00101   if (set_p && !ACE_BIT_ENABLED (options.creation_flags (),
00102                                  ACE_Process_Options::NO_EXEC))
00103     {
00104       int maxlen = 0;
00105       ACE_TCHAR *cmd_line_buf = options.command_line_buf (&maxlen);
00106       size_t max_len = static_cast<size_t> (maxlen);
00107       size_t curr_len = ACE_OS::strlen (cmd_line_buf);
00108       ACE_Handle_Set_Iterator h_iter (*set_p);
00109       // Because the length of the to-be-formatted +H option is not
00110       // known, and we don't have a snprintf, guess at the space
00111       // needed (20 chars), and use that as a limit.
00112       for (ACE_HANDLE h = h_iter ();
00113            h != ACE_INVALID_HANDLE && curr_len + 20 < max_len;
00114            h = h_iter ())
00115         {
00116 #if defined (ACE_WIN32)
00117 # if defined (ACE_WIN64)
00118           curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
00119                                        ACE_TEXT (" +H %I64p"),
00120                                        h);
00121 # else
00122           curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
00123                                        ACE_TEXT (" +H %p"),
00124                                        h);
00125 # endif  /* ACE_WIN64 */
00126 #else
00127           curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
00128                                        ACE_TEXT (" +H %d"),
00129                                        h);
00130 #endif /* ACE_WIN32 */
00131         }
00132     }
00133 
00134 #if defined (ACE_HAS_WINCE)
00135   // Note that WinCE does not have process name included in the command line as argv[0]
00136   // like other OS environment.  Therefore, it is user's whole responsibility to call
00137   // 'ACE_Process_Options::process_name(const ACE_TCHAR *name)' to set the proper
00138   // process name (the execution file name with path if needed).
00139 
00140   BOOL fork_result =
00141     ACE_TEXT_CreateProcess (options.process_name(),
00142                             options.command_line_buf(),
00143                             options.get_process_attributes(),  // must be NULL in CE
00144                             options.get_thread_attributes(),   // must be NULL in CE
00145                             options.handle_inheritence(),      // must be false in CE
00146                             options.creation_flags(),          // must be NULL in CE
00147                             options.env_buf(),                 // environment variables, must be NULL in CE
00148                             options.working_directory(),       // must be NULL in CE
00149                             options.startup_info(),            // must be NULL in CE
00150                             &this->process_info_);
00151 
00152   if (fork_result)
00153     {
00154       parent (this->getpid ());
00155       return this->getpid ();
00156     }
00157   return ACE_INVALID_PID;
00158 
00159 #elif defined (ACE_WIN32)
00160   BOOL fork_result =
00161     ACE_TEXT_CreateProcess (0,
00162                             options.command_line_buf (),
00163                             options.get_process_attributes (),
00164                             options.get_thread_attributes (),
00165                             options.handle_inheritence (),
00166                             options.creation_flags (),
00167                             options.env_buf (), // environment variables
00168                             options.working_directory (),
00169                             options.startup_info (),
00170                             &this->process_info_);
00171 
00172   if (fork_result)
00173     {
00174       parent (this->getpid ());
00175       return this->getpid ();
00176     }
00177   return ACE_INVALID_PID;
00178 
00179 #elif defined(ACE_OPENVMS)
00180   if (ACE_BIT_ENABLED (options.creation_flags (),
00181                        ACE_Process_Options::NO_EXEC))
00182     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00183 
00184   int saved_stdin = ACE_STDIN;
00185   int saved_stdout = ACE_STDOUT;
00186   int saved_stderr = ACE_STDERR;
00187   // Save STD file descriptors and redirect
00188   if (options.get_stdin () != ACE_INVALID_HANDLE) {
00189     if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
00190       ACE_OS::exit (errno);
00191     if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
00192       ACE_OS::exit (errno);
00193   }
00194   if (options.get_stdout () != ACE_INVALID_HANDLE) {
00195     if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
00196       ACE_OS::exit (errno);
00197     if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
00198       ACE_OS::exit (errno);
00199   }
00200   if (options.get_stderr () != ACE_INVALID_HANDLE) {
00201     if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
00202       ACE_OS::exit (errno);
00203     if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
00204       ACE_OS::exit (errno);
00205   }
00206 
00207   if (options.working_directory () != 0)
00208     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00209 
00210   this->child_id_ = vfork();
00211   if (this->child_id_ == 0) {
00212       ACE_OS::execvp (options.process_name (),
00213                 options.command_line_argv ());
00214       // something went wrong
00215       this->child_id_ = ACE_INVALID_PID;
00216   }
00217 
00218   // restore STD file descriptors (if necessary)
00219   if (options.get_stdin () != ACE_INVALID_HANDLE) {
00220     if (saved_stdin == -1)
00221       ACE_OS::close (ACE_STDIN);
00222     else
00223       ACE_OS::dup2 (saved_stdin, ACE_STDIN);
00224   }
00225   if (options.get_stdout () != ACE_INVALID_HANDLE) {
00226     if (saved_stdout == -1)
00227       ACE_OS::close (ACE_STDOUT);
00228     else
00229       ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
00230   }
00231   if (options.get_stderr () != ACE_INVALID_HANDLE) {
00232     if (saved_stderr == -1)
00233       ACE_OS::close (ACE_STDERR);
00234     else
00235       ACE_OS::dup2 (saved_stderr, ACE_STDERR);
00236   }
00237 
00238   return this->child_id_;
00239 #elif (defined (ACE_VXWORKS) && (ACE_VXWORKS > 0x600)) && defined (__RTP__)
00240   if (ACE_BIT_ENABLED (options.creation_flags (),
00241                        ACE_Process_Options::NO_EXEC))
00242     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00243 
00244   if (options.working_directory () != 0)
00245     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00246 
00247   int saved_stdin = ACE_STDIN;
00248   int saved_stdout = ACE_STDOUT;
00249   int saved_stderr = ACE_STDERR;
00250   // Save STD file descriptors and redirect
00251   if (options.get_stdin () != ACE_INVALID_HANDLE) {
00252     if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
00253       ACE_OS::exit (errno);
00254     if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
00255       ACE_OS::exit (errno);
00256   }
00257   if (options.get_stdout () != ACE_INVALID_HANDLE) {
00258     if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
00259       ACE_OS::exit (errno);
00260     if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
00261       ACE_OS::exit (errno);
00262   }
00263   if (options.get_stderr () != ACE_INVALID_HANDLE) {
00264     if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
00265       ACE_OS::exit (errno);
00266     if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
00267       ACE_OS::exit (errno);
00268   }
00269 
00270   // Wide-char builds need narrow-char strings for commandline and
00271   // environment variables.
00272 # if defined (ACE_USES_WCHAR)
00273   wchar_t * const *wargv = options.command_line_argv ();
00274   size_t vcount, i;
00275   for (vcount = 0; wargv[vcount] != 0; ++vcount)
00276     ;
00277   char **procargv = new char *[vcount + 1];  // Need 0 at the end
00278   procargv[vcount] = 0;
00279   for (i = 0; i < vcount; ++i)
00280     procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00281 
00282   char **procenv = 0;
00283   if (options.inherit_environment ())
00284     {
00285       wargv = options.env_argv ();
00286       for (vcount = 0; wargv[vcount] != 0; ++vcount)
00287         ;
00288       procenv = new char *[vcount + 1];  // Need 0 at the end
00289       procenv[vcount] = 0;
00290       for (i = 0; i < vcount; ++i)
00291         procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00292     }
00293 # else
00294   const char **procargv = const_cast<const char**> (options.command_line_argv ());
00295   const char **procenv = const_cast<const char**> (options.env_argv ());
00296 # endif /* ACE_USES_WCHAR */
00297 
00298   this->child_id_ = ::rtpSpawn (procargv[0],
00299                                 procargv,
00300                                 procenv,
00301                                 200,          // priority
00302                                 0x10000,      // uStackSize
00303                                 0,            // options
00304                                 VX_FP_TASK);  // taskOptions
00305   int my_errno_ = errno;
00306   if (this->child_id_ == ERROR) {
00307       // something went wrong
00308       this->child_id_ = ACE_INVALID_PID;
00309   }
00310 
00311 # if defined (ACE_USES_WCHAR)
00312   if (procenv)
00313     delete procenv;
00314 # endif /* ACE_USES_WCHAR */
00315 
00316   // restore STD file descriptors (if necessary)
00317   if (options.get_stdin () != ACE_INVALID_HANDLE) {
00318     if (saved_stdin == -1)
00319       ACE_OS::close (ACE_STDIN);
00320     else
00321       ACE_OS::dup2 (saved_stdin, ACE_STDIN);
00322   }
00323   if (options.get_stdout () != ACE_INVALID_HANDLE) {
00324     if (saved_stdout == -1)
00325       ACE_OS::close (ACE_STDOUT);
00326     else
00327       ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
00328   }
00329   if (options.get_stderr () != ACE_INVALID_HANDLE) {
00330     if (saved_stderr == -1)
00331       ACE_OS::close (ACE_STDERR);
00332     else
00333       ACE_OS::dup2 (saved_stderr, ACE_STDERR);
00334   }
00335 
00336   if (this->child_id_ == ACE_INVALID_PID) {
00337     errno = my_errno_;
00338   }
00339 
00340   return this->child_id_;
00341 #else /* ACE_WIN32 */
00342   // Fork the new process.
00343   this->child_id_ = ACE::fork (options.process_name (),
00344                                options.avoid_zombies ());
00345 
00346   if (this->child_id_ == 0)
00347     {
00348 # if !defined (ACE_LACKS_SETPGID)
00349       // If we're the child and the options specified a non-default
00350       // process group, try to set our pgid to it.  This allows the
00351       // <ACE_Process_Manager> to wait for processes by their
00352       // process-group.
00353       if (options.getgroup () != ACE_INVALID_PID
00354           && ACE_OS::setpgid (0,
00355                               options.getgroup ()) < 0)
00356         ACE_ERROR ((LM_ERROR,
00357                     ACE_TEXT ("%p.\n"),
00358                     ACE_TEXT ("ACE_Process::spawn: setpgid failed.")));
00359 # endif /* ACE_LACKS_SETPGID */
00360 
00361 # if !defined (ACE_LACKS_SETREGID)
00362       if (options.getrgid () != (uid_t) -1
00363           || options.getegid () != (uid_t) -1)
00364         if (ACE_OS::setregid (options.getrgid (),
00365                               options.getegid ()) == -1)
00366           ACE_ERROR ((LM_ERROR,
00367                       ACE_TEXT ("%p.\n"),
00368                       ACE_TEXT ("ACE_Process::spawn: setregid failed.")));
00369 # endif /* ACE_LACKS_SETREGID */
00370 
00371 # if !defined (ACE_LACKS_SETREUID)
00372       // Set user and group id's.
00373       if (options.getruid () != (uid_t) -1
00374           || options.geteuid () != (uid_t) -1)
00375         if (ACE_OS::setreuid (options.getruid (),
00376                               options.geteuid ()) == -1)
00377           ACE_ERROR ((LM_ERROR,
00378                       ACE_TEXT ("%p.\n"),
00379                       ACE_TEXT ("ACE_Process::spawn: setreuid failed.")));
00380 # endif /* ACE_LACKS_SETREUID */
00381 
00382       this->child (ACE_OS::getppid ());
00383     }
00384   else if (this->child_id_ != -1)
00385     this->parent (this->child_id_);
00386 
00387   // If we're not supposed to exec, return the process id.
00388   if (ACE_BIT_ENABLED (options.creation_flags (),
00389                        ACE_Process_Options::NO_EXEC))
00390     return this->child_id_;
00391 
00392   switch (this->child_id_)
00393     {
00394     case -1:
00395       // Error.
00396       return ACE_INVALID_PID;
00397     case 0:
00398       // Child process...exec the
00399       {
00400         if (options.get_stdin () != ACE_INVALID_HANDLE
00401             && ACE_OS::dup2 (options.get_stdin (),
00402                              ACE_STDIN) == -1)
00403           ACE_OS::exit (errno);
00404         else if (options.get_stdout () != ACE_INVALID_HANDLE
00405                  && ACE_OS::dup2 (options.get_stdout (),
00406                                   ACE_STDOUT) == -1)
00407           ACE_OS::exit (errno);
00408         else if (options.get_stderr () != ACE_INVALID_HANDLE
00409                  && ACE_OS::dup2 (options.get_stderr (),
00410                                   ACE_STDERR) == -1)
00411           ACE_OS::exit (errno);
00412 
00413         // close down unneeded descriptors
00414         ACE_OS::close (options.get_stdin ());
00415         ACE_OS::close (options.get_stdout ());
00416         ACE_OS::close (options.get_stderr ());
00417 
00418         // If we must, set the working directory for the child
00419         // process.
00420         if (options.working_directory () != 0)
00421           ACE_OS::chdir (options.working_directory ());
00422         // Should check for error here!
00423 
00424         // Child process executes the command.
00425         int result = 0;
00426 
00427         // Wide-char builds not on Windows need narrow-char strings for
00428         // exec() and environment variables. Don't need to worry about
00429         // releasing any of the converted string memory since this
00430         // process will either exec() or exit() shortly.
00431 # if defined (ACE_USES_WCHAR)
00432         ACE_Wide_To_Ascii n_procname (options.process_name ());
00433         const char *procname = n_procname.char_rep ();
00434 
00435         wchar_t * const *wargv = options.command_line_argv ();
00436         size_t vcount, i;
00437         for (vcount = 0; wargv[vcount] != 0; ++vcount)
00438           ;
00439         char **procargv = new char *[vcount + 1];  // Need 0 at the end
00440         procargv[vcount] = 0;
00441         for (i = 0; i < vcount; ++i)
00442           procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00443 
00444         wargv = options.env_argv ();
00445         for (vcount = 0; wargv[vcount] != 0; ++vcount)
00446           ;
00447         char **procenv = new char *[vcount + 1];  // Need 0 at the end
00448         procenv[vcount] = 0;
00449         for (i = 0; i < vcount; ++i)
00450           procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00451 # else
00452         const char *procname = options.process_name ();
00453         char *const *procargv = options.command_line_argv ();
00454         char *const *procenv = options.env_argv ();
00455 # endif /* ACE_USES_WCHAR */
00456 
00457         if (options.inherit_environment ())
00458           {
00459             // Add the new environment variables to the environment
00460             // context of the context before doing an <execvp>.
00461             for (size_t i = 0; procenv[i] != 0; i++)
00462               if (ACE_OS::putenv (procenv[i]) != 0)
00463                 return ACE_INVALID_PID;
00464 
00465             // Now the forked process has both inherited variables and
00466             // the user's supplied variables.
00467             result = ACE_OS::execvp (procname, procargv);
00468           }
00469         else
00470           {
00471 # if defined (ghs)
00472             // GreenHills 1.8.8 (for VxWorks 5.3.x) can't compile this
00473             // code.  Processes aren't supported on VxWorks anyways.
00474             ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00475 # else
00476             result = ACE_OS::execve (procname, procargv, procenv);
00477 # endif /* ghs */
00478           }
00479         if (result == -1)
00480           {
00481             // If the execv fails, this child needs to exit.
00482 
00483             // Exit with the errno so that the calling process can
00484             // catch this and figure out what went wrong.
00485             ACE_OS::_exit (errno);
00486           }
00487         // ... otherwise, this is never reached.
00488         return 0;
00489       }
00490     default:
00491       // Server process.  The fork succeeded.
00492       return this->child_id_;
00493     }
00494 #endif /* ACE_WIN32 */
00495 }

ACE_INLINE int ACE_Process::terminate void   ) 
 

Terminate the process abruptly using <ACE::terminate_process>. This call doesn't give the process a chance to cleanup, so use it with caution...

Definition at line 71 of file Process.inl.

References getpid(), and ACE::terminate_process().

00072 {
00073   if (this->getpid () != -1)
00074     return ACE::terminate_process (this->getpid ());
00075   else
00076     return -1;
00077 }

void ACE_Process::unmanage void   )  [virtual]
 

Called by a that is removing this Process from its table of managed Processes. Default is to do nothing.

Reimplemented in ACE_Managed_Process.

Definition at line 510 of file Process.cpp.

Referenced by ACE_Process_Manager::remove_proc().

00511 {
00512   // nothing to do
00513 }

pid_t ACE_Process::wait const ACE_Time_Value tv,
ACE_exitcode status = 0
 

Timed wait for the process we've created to exit. A return value of -1 indicates that the something failed; 0 indicates that a timeout occurred. Otherwise, the child's process id is returned. If != 0, it points to an integer where the function stores the child's exit status.

Note:
On UNIX platforms this function uses , i.e., it overwrites any existing alarm. In addition, it steals all s during the timeout period, which will break another in the same process that's expecting to kick off process reaping.

Definition at line 535 of file Process.cpp.

References ACE_exitcode, ACE_INVALID_PID, ACE_SignalHandler, ETIME, exit_code_, getpid(), ACE_Time_Value::msec(), pid_t, process_info_, ACE_Sig_Action::register_action(), ACE_OS::set_errno_to_last_error(), SIGCHLD, ACE_OS::sleep(), ACE_Countdown_Time::update(), wait(), ACE_OS::waitpid(), and WNOHANG.

00537 {
00538 #if defined (ACE_WIN32)
00539   // Don't try to get the process exit status if wait failed so we can
00540   // keep the original error code intact.
00541   switch (::WaitForSingleObject (process_info_.hProcess,
00542                                  tv.msec ()))
00543     {
00544     case WAIT_OBJECT_0:
00545         // The error status of <GetExitCodeProcess> is nonetheless not
00546         // tested because we don't know how to return the value.
00547         ::GetExitCodeProcess (process_info_.hProcess,
00548                               &this->exit_code_);
00549       if (status != 0)
00550         *status = this->exit_code_;
00551       return this->getpid ();
00552     case WAIT_TIMEOUT:
00553       errno = ETIME;
00554       return 0;
00555     default:
00556       ACE_OS::set_errno_to_last_error ();
00557       return -1;
00558     }
00559 #elif defined(ACE_LACKS_UNIX_SIGNALS)
00560   if (tv == ACE_Time_Value::zero)
00561     {
00562       pid_t retv =
00563         ACE_OS::waitpid (this->child_id_,
00564                          &this->exit_code_,
00565                          WNOHANG);
00566       if (status != 0)
00567         *status = this->exit_code_;
00568 
00569       return retv;
00570     }
00571 
00572   if (tv == ACE_Time_Value::max_time)
00573 # if defined (ACE_VXWORKS)
00574     {
00575       pid_t retv;
00576       while ( (retv = this->wait (status)) == ACE_INVALID_PID && errno == EINTR ) ;
00577       return retv;
00578     }
00579 # else
00580      return this->wait (status);
00581 # endif
00582 
00583   pid_t pid = 0;
00584   ACE_Time_Value sleeptm (1);    // 1 msec
00585   if (sleeptm > tv)              // if sleeptime > waittime
00586       sleeptm = tv;
00587   ACE_Time_Value tmo (tv);       // Need one we can change
00588   for (ACE_Countdown_Time time_left (&tmo); tmo > ACE_Time_Value::zero ; time_left.update ())
00589     {
00590       pid = ACE_OS::waitpid (this->getpid (),
00591                              &this->exit_code_,
00592                              WNOHANG);
00593       if (status != 0)
00594         *status = this->exit_code_;
00595 
00596       if (pid > 0 || pid == ACE_INVALID_PID)
00597         break;          // Got a child or an error - all done
00598 
00599       // pid 0, nothing is ready yet, so wait.
00600       // Do a (very) short sleep (only this thread sleeps).
00601       ACE_OS::sleep (sleeptm);
00602     }
00603 
00604   return pid;
00605 #else /* !ACE_WIN32 && !ACE_LACKS_UNIX_SIGNALS */
00606   if (tv == ACE_Time_Value::zero)
00607     {
00608       pid_t retv =
00609         ACE_OS::waitpid (this->child_id_,
00610                          &this->exit_code_,
00611                          WNOHANG);
00612       if (status != 0)
00613         *status = this->exit_code_;
00614 
00615       return retv;
00616     }
00617 
00618   if (tv == ACE_Time_Value::max_time)
00619     return this->wait (status);
00620 
00621   // Need to wait but limited to specified time.
00622   // Force generation of SIGCHLD, even though we don't want to
00623   // catch it - just need it to interrupt the sleep below.
00624   // If this object has a reactor set, assume it was given at
00625   // open(), and there's already a SIGCHLD action set, so no
00626   // action is needed here.
00627   ACE_Sig_Action old_action;
00628   ACE_Sig_Action do_sigchld ((ACE_SignalHandler)sigchld_nop);
00629   do_sigchld.register_action (SIGCHLD, &old_action);
00630 
00631   pid_t pid;
00632   ACE_Time_Value tmo (tv);       // Need one we can change
00633   for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
00634     {
00635       pid = ACE_OS::waitpid (this->getpid (),
00636                              &this->exit_code_,
00637                              WNOHANG);
00638       if (status != 0)
00639         *status = this->exit_code_;
00640 
00641       if (pid > 0 || pid == ACE_INVALID_PID)
00642         break;          // Got a child or an error - all done
00643 
00644       // pid 0, nothing is ready yet, so wait.
00645       // Do a sleep (only this thread sleeps) til something
00646       // happens. This relies on SIGCHLD interrupting the sleep.
00647       // If SIGCHLD isn't delivered, we'll need to do something
00648       // with sigaction to force it.
00649       if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
00650         continue;
00651       // Timed out
00652       pid = 0;
00653       break;
00654     }
00655 
00656   // Restore the previous SIGCHLD action if it was changed.
00657   old_action.register_action (SIGCHLD);
00658 
00659   return pid;
00660 #endif /* ACE_WIN32 */
00661 }

ACE_INLINE pid_t ACE_Process::wait ACE_exitcode status = 0,
int  wait_options = 0
 

Wait for the process we've created to exit. If != 0, it points to an integer where the function store the exit status of child process to. If == then return 0 and don't block if the child process hasn't exited yet. A return value of -1 represents the operation failed, otherwise, the child process id is returned.

Definition at line 44 of file Process.inl.

References ACE_exitcode, exit_code_, pid_t, process_info_, and ACE_OS::wait().

Referenced by ACE_Process_Manager::wait(), and wait().

00046 {
00047   pid_t retv =
00048     ACE_OS::wait (this->getpid (),
00049                   &this->exit_code_,
00050                   wait_options
00051 #if defined (ACE_WIN32)
00052                   , process_info_.hProcess
00053 #endif /* ACE_WIN32 */
00054                   );
00055   if (status != 0)
00056     *status = this->exit_code_;
00057 
00058   return retv;
00059 }


Friends And Related Function Documentation

friend class ACE_Process_Manager [friend]
 

Definition at line 450 of file Process.h.


Member Data Documentation

ACE_Handle_Set ACE_Process::dup_handles_ [protected]
 

Handle duplicates made for the child process.

Definition at line 582 of file Process.h.

ACE_exitcode ACE_Process::exit_code_ [protected]
 

Definition at line 577 of file Process.h.

Referenced by exit_code(), return_value(), and wait().

ACE_Handle_Set ACE_Process::handles_passed_ [protected]
 

Set of handles that were passed to the child process.

Definition at line 580 of file Process.h.

PROCESS_INFORMATION ACE_Process::process_info_ [protected]
 

Definition at line 572 of file Process.h.

Referenced by gethandle(), process_info(), spawn(), and wait().


The documentation for this class was generated from the following files:
Generated on Sun Jan 27 12:56:25 2008 for ACE by doxygen 1.3.6