Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

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 Methods

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

virtual ~ACE_Process (void)
 Destructor. More...

virtual int prepare (ACE_Process_Options &options)
virtual pid_t spawn (ACE_Process_Options &options)
virtual void parent (pid_t child)
 Called just after <ACE_OS::fork> in the parent's context, if the <fork> succeeds. The default is to do nothing. More...

virtual void child (pid_t parent)
virtual void unmanage (void)
 Called by a <Process_Manager> that is removing this Process from its table of managed Processes. Default is to do nothing. More...

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)
 Send the process a signal. This is only portable to operating systems that support signals, such as UNIX/POSIX. More...

int terminate (void)
pid_t getpid (void) const
 Return the process id of the new child process. More...

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

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

ACE_exitcode 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. More...

int return_value (void) const
 Return the Process' return value. This method returns the actual return value that a child process returns or <exit>s. More...

void close_dup_handles (void)
 Close all the handles in the set obtained from the More...

void close_passed_handles (void)
 Close all the handles in the set obtained from the More...

PROCESS_INFORMATION process_info (void)

Protected Methods

void exit_code (ACE_exitcode code)
 Set this process' <exit_code_>. ACE_Process_Manager uses this method to set the <exit_code_> after successfully waiting for this proecess to exit. More...


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

ACE_Handle_Set dup_handles_
 Handle duplicates made for the child process. More...


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


Constructor & Destructor Documentation

ACE_Process::ACE_Process void   
 

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

Definition at line 31 of file Process.cpp.

References ACE_INVALID_PID, and ACE_OS_String::memset.

00032   :
00033 #if !defined (ACE_WIN32)
00034   child_id_ (ACE_INVALID_PID),
00035 #endif /* !defined (ACE_WIN32) */
00036   exit_code_ (0)
00037 {
00038 #if defined (ACE_WIN32)
00039   ACE_OS::memset ((void *) &this->process_info_,
00040                   0,
00041                   sizeof this->process_info_);
00042 #endif /* ACE_WIN32 */
00043 }

ACE_Process::~ACE_Process void    [virtual]
 

Destructor.

Definition at line 45 of file Process.cpp.

References ACE_OS::close, and close_dup_handles.

00046 {
00047 #if defined (ACE_WIN32)
00048   // Free resources allocated in kernel.
00049   ACE_OS::close (this->process_info_.hThread);
00050   ACE_OS::close (this->process_info_.hProcess);
00051 #endif /* ACE_WIN32 */
00052   // If any handles were duplicated for the child process and
00053   // still not closed, get them now.
00054   this->close_dup_handles ();
00055 }


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

References pid_t.

Referenced by spawn.

00330 {
00331   // nothing to do
00332 }

void ACE_Process::close_dup_handles void   
 

Close all the handles in the set obtained from the

Definition at line 440 of file Process.cpp.

References ACE_OS::closesocket, dup_handles_, ACE_Handle_Set::num_set, and ACE_Handle_Set::reset.

Referenced by ~ACE_Process.

00441 {
00442   if (this->dup_handles_.num_set () > 0)
00443     {
00444       ACE_Handle_Set_Iterator h_iter (this->dup_handles_);
00445       for (ACE_HANDLE h = h_iter ();
00446            h != ACE_INVALID_HANDLE;
00447            h = h_iter ())
00448         ACE_OS::closesocket (h);
00449       this->dup_handles_.reset ();
00450     }
00451   return;
00452 }

void ACE_Process::close_passed_handles void   
 

Close all the handles in the set obtained from the

Definition at line 455 of file Process.cpp.

References ACE_OS::closesocket, handles_passed_, ACE_Handle_Set::num_set, and ACE_Handle_Set::reset.

00456 {
00457   if (this->handles_passed_.num_set () > 0)
00458     {
00459       ACE_Handle_Set_Iterator h_iter (this->handles_passed_);
00460       for (ACE_HANDLE h = h_iter ();
00461            h != ACE_INVALID_HANDLE;
00462            h = h_iter ())
00463         ACE_OS::closesocket (h);
00464       this->handles_passed_.reset ();
00465     }
00466   return;
00467 }

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 proecess to exit.

Definition at line 87 of file Process.i.

References ACE_exitcode, and exit_code_.

00088 {
00089   this->exit_code_ = code;
00090 }

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 81 of file Process.i.

References exit_code_.

Referenced by ACE_Process_Manager::notify_proc_handler.

00082 {
00083   return this->exit_code_;
00084 }

ACE_INLINE ACE_HANDLE ACE_Process::gethandle void    const
 

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

Definition at line 14 of file Process.i.

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.

00015 {
00016 #if defined (ACE_WIN32)
00017   return process_info_.hProcess;
00018 #else
00019   return ACE_HANDLE (child_id_);
00020 #endif /* ACE_WIN32 */
00021 }

ACE_INLINE pid_t ACE_Process::getpid void    const
 

Return the process id of the new child process.

Definition at line 24 of file Process.i.

Referenced by ACE_Process_Manager::find_proc, ACE_Process_Manager::handle_signal, ACE_Process_Manager::insert_proc, kill, spawn, terminate, ACE_Process_Manager::wait, and wait.

00026 {
00027 #if defined (ACE_WIN32)
00028   return process_info_.dwProcessId;
00029 #else /* ACE_WIN32 */
00030   return child_id_;
00031 #endif /* ACE_WIN32 */
00032 }

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 53 of file Process.i.

References getpid, and ACE_OS::kill.

00054 {
00055   if (this->getpid () != -1)
00056     return ACE_OS::kill (this->getpid (), signum);
00057   else
00058     return -1;
00059 }

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

References pid_t.

Referenced by spawn.

00324 {
00325   // nothing to do
00326 }

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

Referenced by spawn.

00059 {
00060   return 0;
00061 }

PROCESS_INFORMATION ACE_Process::process_info void   
 

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 71 of file Process.i.

References exit_code_, and WEXITSTATUS.

00072 {
00073 #if defined (ACE_WIN32)
00074   return this->exit_code_;
00075 #else
00076   return WEXITSTATUS (this->exit_code_);
00077 #endif /* ACE_WIN32 */
00078 }

int ACE_Process::running void    const
 

Return 1 if running; 0 otherwise.

Definition at line 341 of file Process.cpp.

References gethandle, and ACE_OS::kill.

00342 {
00343 #if defined (ACE_WIN32)
00344     DWORD code;
00345 
00346     BOOL result = ::GetExitCodeProcess (this->gethandle (),
00347                                         &code);
00348     return result && code == STILL_ACTIVE;
00349 #else
00350     return ACE_OS::kill (this->getpid (),
00351                          0) == 0
00352       || errno != ESRCH;
00353 #endif /* ACE_WIN32 */
00354 }

pid_t ACE_Process::spawn ACE_Process_Options   options [virtual]
 

Launch a new process as described by <options>. Returns the process id of the newly spawned child on success or -1 on failure.

Definition at line 64 of file Process.cpp.

References ACE_OS::_exit, ACE_BIT_ENABLED, ACE_ERROR, ACE_INVALID_PID, ACE_LIB_TEXT, 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::dup2, ACE_Process_Options::dup_handles, 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_OS::getppid, ACE_Process_Options::handle_inheritence, handles_passed_, ACE_Process_Options::inherit_environment, LM_ERROR, ACE_Process_Options::NO_EXEC, 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_String::strlen, and ACE_Process_Options::working_directory.

Referenced by ACE_Process_Manager::spawn.

00065 {
00066   if (prepare (options) < 0)
00067     return ACE_INVALID_PID;
00068 
00069   // Stash the passed/duped handle sets away in this object for later
00070   // closing if needed or requested. At the same time, figure out which
00071   // ones to include in command line options if that's needed below.
00072   ACE_Handle_Set *set_p = 0;
00073   if (options.dup_handles (this->dup_handles_))
00074     set_p = &this->dup_handles_;
00075   else if (options.passed_handles (this->handles_passed_))
00076     set_p = &this->handles_passed_;
00077 
00078   // If we are going to end up running a new program (i.e. Win32, or
00079   // NO_EXEC option is set) then get any handles passed in the options,
00080   // and tack them onto the command line with +H <handle> options,
00081   // unless the command line runs out of space.
00082   // Note that we're using the knowledge that all the options, argvs, etc.
00083   // passed to the options are all sitting in the command_line_buf. Any
00084   // call to get the argv then splits them out. So, regardless of the
00085   // platform, tack them all onto the command line buf and take it
00086   // from there.
00087   if (set_p && !ACE_BIT_ENABLED (options.creation_flags (),
00088                                  ACE_Process_Options::NO_EXEC))
00089     {
00090       int maxlen = 0;
00091       ACE_TCHAR *cmd_line_buf = options.command_line_buf (&maxlen);
00092       size_t max_len = ACE_static_cast (size_t, maxlen);
00093       size_t curr_len = ACE_OS::strlen (cmd_line_buf);
00094       ACE_Handle_Set_Iterator h_iter (*set_p);
00095       // Because the length of the to-be-formatted +H option is not
00096       // known, and we don't have a snprintf, guess at the space
00097       // needed (20 chars), and use that as a limit.
00098       for (ACE_HANDLE h = h_iter ();
00099            h != ACE_INVALID_HANDLE && curr_len + 20 < max_len;
00100            h = h_iter ())
00101         {
00102           curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
00103                                        ACE_LIB_TEXT (" +H %d"),
00104                                        h);
00105         }
00106     }
00107 
00108 #if defined (ACE_HAS_WINCE)
00109   // Note that WinCE does not have process name included in the command line as argv[0]
00110   // like other OS environment.  Therefore, it is user's whole responsibility to call
00111   // 'ACE_Process_Options::process_name(const ACE_TCHAR *name)' to set the proper
00112   // process name (the execution file name with path if needed).
00113 
00114   BOOL fork_result =
00115     ACE_TEXT_CreateProcess (options.process_name(),
00116                             options.command_line_buf(),
00117                             options.get_process_attributes(),  // must be NULL in CE
00118                             options.get_thread_attributes(),   // must be NULL in CE
00119                             options.handle_inheritence(),      // must be false in CE
00120                             options.creation_flags(),          // must be NULL in CE
00121                             options.env_buf(),                 // environment variables, must be NULL in CE
00122                             options.working_directory(),       // must be NULL in CE
00123                             options.startup_info(),            // must be NULL in CE
00124                             &this->process_info_);
00125 
00126   if (fork_result)
00127     {
00128       parent (this->getpid ());
00129       return this->getpid ();
00130     }
00131   return ACE_INVALID_PID;
00132 
00133 #elif defined (ACE_WIN32)
00134   BOOL fork_result =
00135     ACE_TEXT_CreateProcess (0,
00136                             options.command_line_buf (),
00137                             options.get_process_attributes (),
00138                             options.get_thread_attributes (),
00139                             options.handle_inheritence (),
00140                             options.creation_flags (),
00141                             options.env_buf (), // environment variables
00142                             options.working_directory (),
00143                             options.startup_info (),
00144                             &this->process_info_);
00145 
00146   if (fork_result)
00147     {
00148       parent (this->getpid ());
00149       return this->getpid ();
00150     }
00151   return ACE_INVALID_PID;
00152 
00153 #elif defined (CHORUS)
00154   // This only works if we exec.  Chorus does not really support
00155   // forking.
00156   if (ACE_BIT_ENABLED (options.creation_flags (),
00157                        ACE_Process_Options::NO_EXEC))
00158     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00159 
00160   // These are all currently unsupported.
00161   if (options.get_stdin () != ACE_INVALID_HANDLE)
00162     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00163   if (options.get_stdout () != ACE_INVALID_HANDLE)
00164     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00165   if (options.get_stderr () != ACE_INVALID_HANDLE)
00166     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00167   if (options.working_directory () != 0)
00168     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00169 
00170   if (options.env_argv ()[0] == 0)
00171     // command-line args
00172     this->child_id_ = ACE_OS::execvp (options.process_name (),
00173                                       options.command_line_argv ());
00174   else
00175     {
00176       // Add the new environment variables to the environment context
00177       // of the context before doing an <execvp>.
00178       for (char *const *user_env = options.env_argv ();
00179            *user_env != 0;
00180            user_env++)
00181         if (ACE_OS::putenv (*user_env) != 0)
00182           return ACE_INVALID_PID;
00183 
00184       // Now the forked process has both inherited variables and the
00185       // user's supplied variables.
00186       this->child_id_ = ACE_OS::execvp (options.process_name (),
00187                                         options.command_line_argv ());
00188     }
00189 
00190   return this->child_id_;
00191 #else /* ACE_WIN32 */
00192   // Fork the new process.
00193   this->child_id_ = ACE::fork (options.process_name (),
00194                                options.avoid_zombies ());
00195 
00196   if (this->child_id_ == 0)
00197     {
00198 # if !defined (ACE_LACKS_SETPGID)
00199       // If we're the child and the options specified a non-default
00200       // process group, try to set our pgid to it.  This allows the
00201       // <ACE_Process_Manager> to wait for processes by their
00202       // process-group.
00203       if (options.getgroup () != ACE_INVALID_PID
00204           && ACE_OS::setpgid (0,
00205                               options.getgroup ()) < 0)
00206         ACE_ERROR ((LM_ERROR,
00207                     ACE_LIB_TEXT ("%p.\n"),
00208                     ACE_LIB_TEXT ("ACE_Process::spawn: setpgid failed.")));
00209 # endif /* ACE_LACKS_SETPGID */
00210 
00211 # if !defined (ACE_LACKS_SETREGID)
00212       if (options.getrgid () != (uid_t) -1
00213           || options.getegid () != (uid_t) -1)
00214         if (ACE_OS::setregid (options.getrgid (),
00215                               options.getegid ()) == -1)
00216           ACE_ERROR ((LM_ERROR,
00217                       ACE_LIB_TEXT ("%p.\n"),
00218                       ACE_LIB_TEXT ("ACE_Process::spawn: setregid failed.")));
00219 # endif /* ACE_LACKS_SETREGID */
00220 
00221 # if !defined (ACE_LACKS_SETREUID)
00222       // Set user and group id's.
00223       if (options.getruid () != (uid_t) -1
00224           || options.geteuid () != (uid_t) -1)
00225         if (ACE_OS::setreuid (options.getruid (),
00226                               options.geteuid ()) == -1)
00227           ACE_ERROR ((LM_ERROR,
00228                       ACE_LIB_TEXT ("%p.\n"),
00229                       ACE_LIB_TEXT ("ACE_Process::spawn: setreuid failed.")));
00230 # endif /* ACE_LACKS_SETREUID */
00231 
00232       this->child (ACE_OS::getppid ());
00233     }
00234   else if (this->child_id_ != -1)
00235     this->parent (this->child_id_);
00236 
00237   // If we're not supposed to exec, return the process id.
00238   if (ACE_BIT_ENABLED (options.creation_flags (),
00239                        ACE_Process_Options::NO_EXEC))
00240     return this->child_id_;
00241 
00242   switch (this->child_id_)
00243     {
00244     case -1:
00245       // Error.
00246       return ACE_INVALID_PID;
00247     case 0:
00248       // Child process...exec the
00249       {
00250         if (options.get_stdin () != ACE_INVALID_HANDLE
00251             && ACE_OS::dup2 (options.get_stdin (),
00252                              ACE_STDIN) == -1)
00253           ACE_OS::exit (errno);
00254         else if (options.get_stdout () != ACE_INVALID_HANDLE
00255                  && ACE_OS::dup2 (options.get_stdout (),
00256                                   ACE_STDOUT) == -1)
00257           ACE_OS::exit (errno);
00258         else if (options.get_stderr () != ACE_INVALID_HANDLE
00259                  && ACE_OS::dup2 (options.get_stderr (),
00260                                   ACE_STDERR) == -1)
00261           ACE_OS::exit (errno);
00262 
00263         // close down unneeded descriptors
00264         ACE_OS::close (options.get_stdin ());
00265         ACE_OS::close (options.get_stdout ());
00266         ACE_OS::close (options.get_stderr ());
00267 
00268         // If we must, set the working directory for the child
00269         // process.
00270         if (options.working_directory () != 0)
00271           ACE_OS::chdir (options.working_directory ());
00272         // Should check for error here!
00273 
00274         // Child process executes the command.
00275         int result = 0;
00276 
00277         if (options.inherit_environment ())
00278           {
00279             // Add the new environment variables to the environment
00280             // context of the context before doing an <execvp>.
00281             for (char *const *user_env = options.env_argv ();
00282                  *user_env != 0;
00283                  user_env++)
00284               if (ACE_OS::putenv (*user_env) != 0)
00285                 return ACE_INVALID_PID;
00286 
00287             // Now the forked process has both inherited variables and
00288             // the user's supplied variables.
00289             result = ACE_OS::execvp (options.process_name (),
00290                                      options.command_line_argv ());
00291           }
00292         else
00293           {
00294 #if defined (ghs)
00295             // GreenHills 1.8.8 (for VxWorks 5.3.x) can't compile this
00296             // code.  Processes aren't supported on VxWorks anyways.
00297             ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00298 #else
00299             result = ACE_OS::execve (options.process_name (),
00300                                      options.command_line_argv (),
00301                                      options.env_argv ());
00302 # endif /* ghs */
00303           }
00304         if (result == -1)
00305           {
00306             // If the execv fails, this child needs to exit.
00307 
00308             // Exit with the errno so that the calling process can
00309             // catch this and figure out what went wrong.
00310             ACE_OS::_exit (errno);
00311           }
00312         // ... otherwise, this is never reached.
00313         return 0;
00314       }
00315     default:
00316       // Server process.  The fork succeeded.
00317       return this->child_id_;
00318     }
00319 #endif /* ACE_WIN32 */
00320 }

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 62 of file Process.i.

References getpid, and ACE::terminate_process.

00063 {
00064   if (this->getpid () != -1)
00065     return ACE::terminate_process (this->getpid ());
00066   else
00067     return -1;
00068 }

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

Referenced by ACE_Process_Manager::remove_proc.

00336 {
00337   // nothing to do
00338 }

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

References ACE_exitcode, ACE_INVALID_PID, ACE_SignalHandler, ETIME, exit_code_, getpid, ACE_Time_Value::max_time, 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, WNOHANG, and ACE_Time_Value::zero.

00359 {
00360 #if defined (ACE_WIN32)
00361   // Don't try to get the process exit status if wait failed so we can
00362   // keep the original error code intact.
00363   switch (::WaitForSingleObject (process_info_.hProcess,
00364                                  tv.msec ()))
00365     {
00366     case WAIT_OBJECT_0:
00367         // The error status of <GetExitCodeProcess> is nonetheless not
00368         // tested because we don't know how to return the value.
00369         ::GetExitCodeProcess (process_info_.hProcess,
00370                               &this->exit_code_);
00371       if (status != 0)
00372         *status = this->exit_code_;
00373       return this->getpid ();
00374     case WAIT_TIMEOUT:
00375       errno = ETIME;
00376       return 0;
00377     default:
00378       ACE_OS::set_errno_to_last_error ();
00379       return -1;
00380     }
00381 #else /* ACE_WIN32 */
00382   if (tv == ACE_Time_Value::zero)
00383     {
00384       pid_t retv =
00385         ACE_OS::waitpid (this->child_id_,
00386                          &this->exit_code_,
00387                          WNOHANG);
00388       if (status != 0)
00389         *status = this->exit_code_;
00390 
00391       return retv;
00392     }
00393 
00394   if (tv == ACE_Time_Value::max_time)
00395     return this->wait (status);
00396 
00397   // Need to wait but limited to specified time.
00398   // Force generation of SIGCHLD, even though we don't want to
00399   // catch it - just need it to interrupt the sleep below.
00400   // If this object has a reactor set, assume it was given at
00401   // open(), and there's already a SIGCHLD action set, so no
00402   // action is needed here.
00403   ACE_Sig_Action old_action;
00404   ACE_Sig_Action do_sigchld ((ACE_SignalHandler)sigchld_nop);
00405   do_sigchld.register_action (SIGCHLD, &old_action);
00406 
00407   pid_t pid;
00408   ACE_Time_Value tmo (tv);       // Need one we can change
00409   for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
00410     {
00411       pid = ACE_OS::waitpid (this->getpid (),
00412                              &this->exit_code_,
00413                              WNOHANG);
00414       if (status != 0)
00415         *status = this->exit_code_;
00416 
00417       if (pid > 0 || pid == ACE_INVALID_PID)
00418         break;          // Got a child or an error - all done
00419 
00420       // pid 0, nothing is ready yet, so wait.
00421       // Do a sleep (only this thread sleeps) til something
00422       // happens. This relies on SIGCHLD interrupting the sleep.
00423       // If SIGCHLD isn't delivered, we'll need to do something
00424       // with sigaction to force it.
00425       if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
00426         continue;
00427       // Timed out
00428       pid = 0;
00429       break;
00430     }
00431 
00432   // Restore the previous SIGCHLD action if it was changed.
00433   old_action.register_action (SIGCHLD);
00434 
00435   return pid;
00436 #endif /* ACE_WIN32 */
00437 }

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 35 of file Process.i.

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

Referenced by ACE_Process_Manager::wait, and wait.

00037 {
00038   pid_t retv =
00039     ACE_OS::wait (this->getpid (),
00040                   &this->exit_code_,
00041                   wait_options
00042 #if defined (ACE_WIN32)
00043                   , process_info_.hProcess
00044 #endif /* ACE_WIN32 */
00045                   );
00046   if (status != 0)
00047     *status = this->exit_code_;
00048 
00049   return retv;
00050 }


Friends And Related Function Documentation

friend class ACE_Process_Manager [friend]
 

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

Referenced by close_dup_handles, and spawn.

ACE_exitcode ACE_Process::exit_code_ [protected]
 

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

Referenced by close_passed_handles, and spawn.

PROCESS_INFORMATION ACE_Process::process_info_ [protected]
 

Definition at line 547 of file Process.h.

Referenced by gethandle, spawn, and wait.


The documentation for this class was generated from the following files:
Generated on Mon Jun 16 12:54:27 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002