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 440 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 41 of file Process.cpp.

References ACE_INVALID_PID, and ACE_OS::memset().

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

ACE_Process::~ACE_Process void   )  [virtual]
 

Destructor.

Definition at line 55 of file Process.cpp.

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

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

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

References pid_t.

Referenced by spawn().

00495 {
00496   // nothing to do
00497 }

void ACE_Process::close_dup_handles void   ) 
 

Close all the handles in the set obtained from the

Definition at line 654 of file Process.cpp.

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

Referenced by ~ACE_Process().

00655 {
00656   if (this->dup_handles_.num_set () > 0)
00657     {
00658       ACE_Handle_Set_Iterator h_iter (this->dup_handles_);
00659       for (ACE_HANDLE h = h_iter ();
00660            h != ACE_INVALID_HANDLE;
00661            h = h_iter ())
00662         ACE_OS::closesocket (h);
00663       this->dup_handles_.reset ();
00664     }
00665   return;
00666 }

void ACE_Process::close_passed_handles void   ) 
 

Close all the handles in the set obtained from the

Definition at line 669 of file Process.cpp.

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

00670 {
00671   if (this->handles_passed_.num_set () > 0)
00672     {
00673       ACE_Handle_Set_Iterator h_iter (this->handles_passed_);
00674       for (ACE_HANDLE h = h_iter ();
00675            h != ACE_INVALID_HANDLE;
00676            h = h_iter ())
00677         ACE_OS::closesocket (h);
00678       this->handles_passed_.reset ();
00679     }
00680   return;
00681 }

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

References pid_t.

Referenced by spawn().

00489 {
00490   // nothing to do
00491 }

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

Referenced by spawn().

00069 {
00070   return 0;
00071 }

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

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

00507 {
00508 #if defined (ACE_WIN32)
00509     DWORD code;
00510 
00511     BOOL result = ::GetExitCodeProcess (this->gethandle (),
00512                                         &code);
00513     return result && code == STILL_ACTIVE;
00514 #else
00515   if (ACE_INVALID_PID == this->getpid ())
00516     return 0;
00517   else
00518     return ACE_OS::kill (this->getpid (),
00519                          0) == 0
00520       || errno != ESRCH;
00521 #endif /* ACE_WIN32 */
00522 }

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

References ACE_OS::_exit(), ACE_BIT_ENABLED, ACE_ERROR, ACE_INVALID_PID, ACE_LIB_TEXT, ACE_NOTSUP_RETURN, ACE_STDERR, ACE_STDIN, ACE_STDOUT, ACE_TCHAR, ACE_Process_Options::avoid_zombies(), ACE_OS::chdir(), child(), 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_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().

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

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

Referenced by ACE_Process_Manager::remove_proc().

00501 {
00502   // nothing to do
00503 }

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 525 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.

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

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 443 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 575 of file Process.h.

ACE_exitcode ACE_Process::exit_code_ [protected]
 

Definition at line 570 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 573 of file Process.h.

PROCESS_INFORMATION ACE_Process::process_info_ [protected]
 

Definition at line 565 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 Thu Nov 9 11:27:20 2006 for ACE by doxygen 1.3.6