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)

Protected Member Functions

void exit_code (ACE_exitcode code)

Protected Attributes

pid_t child_id_
 Process id of the child.
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 <setenv> is used, the <spawn> is using the <execve> system call. It means that the <command_line> should include a full path to the program file (<execve> does not search the PATH). If <setenv> is not used then, the <spawn> is using the <execvp> 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_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 526 of file Process.cpp.

Referenced by spawn().

00527 {
00528   // nothing to do
00529 }

void ACE_Process::close_dup_handles ( void   ) 

Close all the handles in the set obtained from the

Definition at line 686 of file Process.cpp.

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

Referenced by ~ACE_Process().

00687 {
00688   if (this->dup_handles_.num_set () > 0)
00689     {
00690       ACE_Handle_Set_Iterator h_iter (this->dup_handles_);
00691       for (ACE_HANDLE h = h_iter ();
00692            h != ACE_INVALID_HANDLE;
00693            h = h_iter ())
00694         ACE_OS::closesocket (h);
00695       this->dup_handles_.reset ();
00696     }
00697   return;
00698 }

void ACE_Process::close_passed_handles ( void   ) 

Close all the handles in the set obtained from the

Definition at line 701 of file Process.cpp.

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

00702 {
00703   if (this->handles_passed_.num_set () > 0)
00704     {
00705       ACE_Handle_Set_Iterator h_iter (this->handles_passed_);
00706       for (ACE_HANDLE h = h_iter ();
00707            h != ACE_INVALID_HANDLE;
00708            h = h_iter ())
00709         ACE_OS::closesocket (h);
00710       this->handles_passed_.reset ();
00711     }
00712   return;
00713 }

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

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

Definition at line 96 of file Process.inl.

References 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 <wait> or <waitpid>). 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_BEGIN_VERSIONED_NAMESPACE_DECL 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 child_id_.

Referenced by ACE_Process_Manager::append_proc(), and running().

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.

References child_id_.

Referenced by ACE_Process_Manager::handle_signal(), ACE_Process_Manager::insert_proc(), spawn(), 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 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 <fork> succeeds. The default is to do nothing.

Definition at line 520 of file Process.cpp.

Referenced by spawn().

00521 {
00522   // nothing to do
00523 }

int ACE_Process::prepare ( ACE_Process_Options options  )  [virtual]

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

Definition at line 72 of file Process.cpp.

00073 {
00074   return 0;
00075 }

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 <exit>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 538 of file Process.cpp.

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

00539 {
00540 #if defined (ACE_WIN32)
00541     DWORD code;
00542 
00543     BOOL result = ::GetExitCodeProcess (this->gethandle (),
00544                                         &code);
00545     return result && code == STILL_ACTIVE;
00546 #else
00547   if (ACE_INVALID_PID == this->getpid ())
00548     return 0;
00549   else
00550     return ACE_OS::kill (this->getpid (),
00551                          0) == 0
00552       || errno != ESRCH;
00553 #endif /* ACE_WIN32 */
00554 }

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_TEXT, ACE_Process_Options::avoid_zombies(), ACE_OS::chdir(), child(), child_id_, ACE_OS::close(), ACE_Process_Options::command_line_argv(), ACE_Process_Options::command_line_buf(), ACE_Process_Options::creation_flags(), ACE_OS::dup(), ACE_OS::dup2(), ACE_Process_Options::dup_handles(), ACE_Process_Options::env_argv(), ACE_Process_Options::env_buf(), ACE_OS::execve(), ACE_OS::execvp(), ACE_OS::exit(), ACE::fork(), ACE_Process_Options::get_stderr(), ACE_Process_Options::get_stdin(), ACE_Process_Options::get_stdout(), ACE_Process_Options::getegid(), ACE_Process_Options::geteuid(), ACE_Process_Options::getgroup(), getpid(), ACE_OS::getppid(), ACE_Process_Options::getrgid(), ACE_Process_Options::getruid(), ACE_Process_Options::handle_inheritence(), ACE_Process_Options::inherit_environment(), LM_ERROR, ACE_Process_Options::NO_EXEC, parent(), ACE_Process_Options::passed_handles(), ACE_Process_Options::process_name(), ACE_OS::putenv(), ACE_OS::setpgid(), ACE_OS::setregid(), ACE_OS::setreuid(), ACE_OS::sprintf(), ACE_OS::strlen(), and ACE_Process_Options::working_directory().

Referenced by ACE_Process_Manager::spawn().

00079 {
00080   if (this->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     {
00338       errno = my_errno_;
00339     }
00340 
00341   return this->child_id_;
00342 #else /* ACE_WIN32 */
00343   // Fork the new process.
00344   this->child_id_ = ACE::fork (options.process_name (),
00345                                options.avoid_zombies ());
00346 
00347   if (this->child_id_ == 0)
00348     {
00349 # if !defined (ACE_LACKS_SETPGID)
00350       // If we're the child and the options specified a non-default
00351       // process group, try to set our pgid to it.  This allows the
00352       // <ACE_Process_Manager> to wait for processes by their
00353       // process-group.
00354       if (options.getgroup () != ACE_INVALID_PID
00355           && ACE_OS::setpgid (0,
00356                               options.getgroup ()) < 0)
00357         {
00358 #if !defined (ACE_HAS_THREADS)
00359           // We can't emit this log message because ACE_ERROR(), etc.
00360           // will invoke async signal unsafe functions, which results
00361           // in undefined behavior in threaded programs.
00362           ACE_ERROR ((LM_ERROR,
00363                       ACE_TEXT ("%p.\n"),
00364                       ACE_TEXT ("ACE_Process::spawn: setpgid failed.")));
00365 #endif
00366         }
00367 # endif /* ACE_LACKS_SETPGID */
00368 
00369 # if !defined (ACE_LACKS_SETREGID)
00370       if (options.getrgid () != (uid_t) -1
00371           || options.getegid () != (uid_t) -1)
00372         if (ACE_OS::setregid (options.getrgid (),
00373                               options.getegid ()) == -1)
00374           {
00375 #if !defined (ACE_HAS_THREADS)
00376             // We can't emit this log message because ACE_ERROR(), etc.
00377             // will invoke async signal unsafe functions, which results
00378             // in undefined behavior in threaded programs.
00379             ACE_ERROR ((LM_ERROR,
00380                         ACE_TEXT ("%p.\n"),
00381                         ACE_TEXT ("ACE_Process::spawn: setregid failed.")));
00382 #endif
00383           }
00384 # endif /* ACE_LACKS_SETREGID */
00385 
00386 # if !defined (ACE_LACKS_SETREUID)
00387       // Set user and group id's.
00388       if (options.getruid () != (uid_t) -1
00389           || options.geteuid () != (uid_t) -1)
00390         if (ACE_OS::setreuid (options.getruid (),
00391                               options.geteuid ()) == -1)
00392           {
00393 #if !defined (ACE_HAS_THREADS)
00394             // We can't emit this log message because ACE_ERROR(), etc.
00395             // will invoke async signal unsafe functions, which results
00396             // in undefined behavior in threaded programs.
00397             ACE_ERROR ((LM_ERROR,
00398                         ACE_TEXT ("%p.\n"),
00399                         ACE_TEXT ("ACE_Process::spawn: setreuid failed.")));
00400 #endif
00401           }
00402 # endif /* ACE_LACKS_SETREUID */
00403 
00404       this->child (ACE_OS::getppid ());
00405     }
00406   else if (this->child_id_ != -1)
00407     this->parent (this->child_id_);
00408 
00409   // If we're not supposed to exec, return the process id.
00410   if (ACE_BIT_ENABLED (options.creation_flags (),
00411                        ACE_Process_Options::NO_EXEC))
00412     return this->child_id_;
00413 
00414   switch (this->child_id_)
00415     {
00416     case -1:
00417       // Error.
00418       return ACE_INVALID_PID;
00419     case 0:
00420       // Child process...exec the
00421       {
00422         if (options.get_stdin () != ACE_INVALID_HANDLE
00423             && ACE_OS::dup2 (options.get_stdin (),
00424                              ACE_STDIN) == -1)
00425           ACE_OS::exit (errno);
00426         else if (options.get_stdout () != ACE_INVALID_HANDLE
00427                  && ACE_OS::dup2 (options.get_stdout (),
00428                                   ACE_STDOUT) == -1)
00429           ACE_OS::exit (errno);
00430         else if (options.get_stderr () != ACE_INVALID_HANDLE
00431                  && ACE_OS::dup2 (options.get_stderr (),
00432                                   ACE_STDERR) == -1)
00433           ACE_OS::exit (errno);
00434 
00435         // close down unneeded descriptors
00436         ACE_OS::close (options.get_stdin ());
00437         ACE_OS::close (options.get_stdout ());
00438         ACE_OS::close (options.get_stderr ());
00439 
00440         // If we must, set the working directory for the child
00441         // process.
00442         if (options.working_directory () != 0)
00443           ACE_OS::chdir (options.working_directory ());
00444         // Should check for error here!
00445 
00446         // Child process executes the command.
00447         int result = 0;
00448 
00449         // Wide-char builds not on Windows need narrow-char strings for
00450         // exec() and environment variables. Don't need to worry about
00451         // releasing any of the converted string memory since this
00452         // process will either exec() or exit() shortly.
00453 # if defined (ACE_USES_WCHAR)
00454         ACE_Wide_To_Ascii n_procname (options.process_name ());
00455         const char *procname = n_procname.char_rep ();
00456 
00457         wchar_t * const *wargv = options.command_line_argv ();
00458         size_t vcount, i;
00459         for (vcount = 0; wargv[vcount] != 0; ++vcount)
00460           ;
00461         char **procargv = new char *[vcount + 1];  // Need 0 at the end
00462         procargv[vcount] = 0;
00463         for (i = 0; i < vcount; ++i)
00464           procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00465 
00466         wargv = options.env_argv ();
00467         for (vcount = 0; wargv[vcount] != 0; ++vcount)
00468           ;
00469         char **procenv = new char *[vcount + 1];  // Need 0 at the end
00470         procenv[vcount] = 0;
00471         for (i = 0; i < vcount; ++i)
00472           procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00473 # else
00474         const char *procname = options.process_name ();
00475         char *const *procargv = options.command_line_argv ();
00476         char *const *procenv = options.env_argv ();
00477 # endif /* ACE_USES_WCHAR */
00478 
00479         if (options.inherit_environment ())
00480           {
00481             // Add the new environment variables to the environment
00482             // context of the context before doing an <execvp>.
00483             for (size_t i = 0; procenv[i] != 0; i++)
00484               if (ACE_OS::putenv (procenv[i]) != 0)
00485                 return ACE_INVALID_PID;
00486 
00487             // Now the forked process has both inherited variables and
00488             // the user's supplied variables.
00489             result = ACE_OS::execvp (procname, procargv);
00490           }
00491         else
00492           {
00493 # if defined (ghs)
00494             // GreenHills 1.8.8 (for VxWorks 5.3.x) can't compile this
00495             // code.  Processes aren't supported on VxWorks anyways.
00496             ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00497 # else
00498             result = ACE_OS::execve (procname, procargv, procenv);
00499 # endif /* ghs */
00500           }
00501         if (result == -1)
00502           {
00503             // If the execv fails, this child needs to exit.
00504 
00505             // Exit with the errno so that the calling process can
00506             // catch this and figure out what went wrong.
00507             ACE_OS::_exit (errno);
00508           }
00509         // ... otherwise, this is never reached.
00510         return 0;
00511       }
00512     default:
00513       // Server process.  The fork succeeded.
00514       return this->child_id_;
00515     }
00516 #endif /* ACE_WIN32 */
00517 }

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 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 <Process_Manager> that is removing this Process from its table of managed Processes. Default is to do nothing.

Reimplemented in ACE_Managed_Process.

Definition at line 532 of file Process.cpp.

Referenced by ACE_Process_Manager::remove_proc().

00533 {
00534   // nothing to do
00535 }

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 <status> != 0, it points to an integer where the function stores the child's exit status.

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

Definition at line 557 of file Process.cpp.

References ACE_INVALID_PID, exit_code_, getpid(), ACE_Time_Value::max_time, ACE_Time_Value::msec(), ACE_Sig_Action::register_action(), ACE_OS::set_errno_to_last_error(), SIGCHLD, sigchld_nop(), ACE_OS::sleep(), wait(), ACE_OS::waitpid(), WNOHANG, and ACE_Time_Value::zero.

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

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 <status> != 0, it points to an integer where the function store the exit status of child process to. If <wait_options> == <WNOHANG> then return 0 and don't block if the child process hasn't exited yet. A return value of -1 represents the <wait> operation failed, otherwise, the child process id is returned.

Definition at line 44 of file Process.inl.

References exit_code_, 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

pid_t ACE_Process::child_id_ [protected]

Process id of the child.

Definition at line 575 of file Process.h.

Referenced by gethandle(), getpid(), and spawn().

ACE_Handle_Set ACE_Process::dup_handles_ [protected]

Handle duplicates made for the child process.

Definition at line 582 of file Process.h.

Referenced by close_dup_handles().

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.

Referenced by close_passed_handles().


The documentation for this class was generated from the following files:
Generated on Tue Feb 2 17:35:26 2010 for ACE by  doxygen 1.4.7