Process.cpp

Go to the documentation of this file.
00001 // $Id: Process.cpp 79134 2007-07-31 18:23:50Z johnnyw $
00002 
00003 #include "ace/Process.h"
00004 
00005 #if !defined (__ACE_INLINE__)
00006 #include "ace/Process.inl"
00007 #endif /* __ACE_INLINE__ */
00008 
00009 #include "ace/ARGV.h"
00010 #include "ace/Auto_Ptr.h"
00011 #include "ace/Signal.h"
00012 #include "ace/SString.h"
00013 #include "ace/Log_Msg.h"
00014 #include "ace/OS_NS_stdio.h"
00015 #include "ace/OS_NS_stdlib.h"
00016 #include "ace/OS_NS_sys_socket.h"
00017 #include "ace/OS_NS_errno.h"
00018 #include "ace/OS_NS_string.h"
00019 #include "ace/OS_NS_unistd.h"
00020 #include "ace/OS_Memory.h"
00021 #include "ace/Countdown_Time.h"
00022 #include "ace/Truncate.h"
00023 
00024 #if defined (ACE_VXWORKS) && (ACE_VXWORKS > 0x600) && defined (__RTP__)
00025 # include <rtpLib.h>
00026 # include <taskLib.h>
00027 #endif
00028 
00029 ACE_RCSID (ace, Process, "$Id: Process.cpp 79134 2007-07-31 18:23:50Z johnnyw $")
00030 
00031 // This function acts as a signal handler for SIGCHLD. We don't really want
00032 // to do anything with the signal - it's just needed to interrupt a sleep.
00033 // See wait() for more info.
00034 #if !defined (ACE_WIN32) && !defined(ACE_LACKS_UNIX_SIGNALS)
00035 static void
00036 sigchld_nop (int, siginfo_t *, ucontext_t *)
00037 {
00038   return;
00039 }
00040 #endif /* ACE_WIN32 */
00041 
00042 
00043 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00044 
00045 ACE_Process::ACE_Process (void)
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 }
00058 
00059 ACE_Process::~ACE_Process (void)
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 }
00070 
00071 int
00072 ACE_Process::prepare (ACE_Process_Options &)
00073 {
00074   return 0;
00075 }
00076 
00077 pid_t
00078 ACE_Process::spawn (ACE_Process_Options &options)
00079 {
00080   if (prepare (options) < 0)
00081     return ACE_INVALID_PID;
00082 
00083   // Stash the passed/duped handle sets away in this object for later
00084   // closing if needed or requested. At the same time, figure out which
00085   // ones to include in command line options if that's needed below.
00086   ACE_Handle_Set *set_p = 0;
00087   if (options.dup_handles (this->dup_handles_))
00088     set_p = &this->dup_handles_;
00089   else if (options.passed_handles (this->handles_passed_))
00090     set_p = &this->handles_passed_;
00091 
00092   // If we are going to end up running a new program (i.e. Win32, or
00093   // NO_EXEC option is set) then get any handles passed in the options,
00094   // and tack them onto the command line with +H <handle> options,
00095   // unless the command line runs out of space.
00096   // Note that we're using the knowledge that all the options, argvs, etc.
00097   // passed to the options are all sitting in the command_line_buf. Any
00098   // call to get the argv then splits them out. So, regardless of the
00099   // platform, tack them all onto the command line buf and take it
00100   // from there.
00101   if (set_p && !ACE_BIT_ENABLED (options.creation_flags (),
00102                                  ACE_Process_Options::NO_EXEC))
00103     {
00104       int maxlen = 0;
00105       ACE_TCHAR *cmd_line_buf = options.command_line_buf (&maxlen);
00106       size_t max_len = static_cast<size_t> (maxlen);
00107       size_t curr_len = ACE_OS::strlen (cmd_line_buf);
00108       ACE_Handle_Set_Iterator h_iter (*set_p);
00109       // Because the length of the to-be-formatted +H option is not
00110       // known, and we don't have a snprintf, guess at the space
00111       // needed (20 chars), and use that as a limit.
00112       for (ACE_HANDLE h = h_iter ();
00113            h != ACE_INVALID_HANDLE && curr_len + 20 < max_len;
00114            h = h_iter ())
00115         {
00116 #if defined (ACE_WIN32)
00117 # if defined (ACE_WIN64)
00118           curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
00119                                        ACE_TEXT (" +H %I64p"),
00120                                        h);
00121 # else
00122           curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
00123                                        ACE_TEXT (" +H %p"),
00124                                        h);
00125 # endif  /* ACE_WIN64 */
00126 #else
00127           curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len],
00128                                        ACE_TEXT (" +H %d"),
00129                                        h);
00130 #endif /* ACE_WIN32 */
00131         }
00132     }
00133 
00134 #if defined (ACE_HAS_WINCE)
00135   // Note that WinCE does not have process name included in the command line as argv[0]
00136   // like other OS environment.  Therefore, it is user's whole responsibility to call
00137   // 'ACE_Process_Options::process_name(const ACE_TCHAR *name)' to set the proper
00138   // process name (the execution file name with path if needed).
00139 
00140   BOOL fork_result =
00141     ACE_TEXT_CreateProcess (options.process_name(),
00142                             options.command_line_buf(),
00143                             options.get_process_attributes(),  // must be NULL in CE
00144                             options.get_thread_attributes(),   // must be NULL in CE
00145                             options.handle_inheritence(),      // must be false in CE
00146                             options.creation_flags(),          // must be NULL in CE
00147                             options.env_buf(),                 // environment variables, must be NULL in CE
00148                             options.working_directory(),       // must be NULL in CE
00149                             options.startup_info(),            // must be NULL in CE
00150                             &this->process_info_);
00151 
00152   if (fork_result)
00153     {
00154       parent (this->getpid ());
00155       return this->getpid ();
00156     }
00157   return ACE_INVALID_PID;
00158 
00159 #elif defined (ACE_WIN32)
00160   BOOL fork_result =
00161     ACE_TEXT_CreateProcess (0,
00162                             options.command_line_buf (),
00163                             options.get_process_attributes (),
00164                             options.get_thread_attributes (),
00165                             options.handle_inheritence (),
00166                             options.creation_flags (),
00167                             options.env_buf (), // environment variables
00168                             options.working_directory (),
00169                             options.startup_info (),
00170                             &this->process_info_);
00171 
00172   if (fork_result)
00173     {
00174       parent (this->getpid ());
00175       return this->getpid ();
00176     }
00177   return ACE_INVALID_PID;
00178 
00179 #elif defined(ACE_OPENVMS)
00180   if (ACE_BIT_ENABLED (options.creation_flags (),
00181                        ACE_Process_Options::NO_EXEC))
00182     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00183 
00184   int saved_stdin = ACE_STDIN;
00185   int saved_stdout = ACE_STDOUT;
00186   int saved_stderr = ACE_STDERR;
00187   // Save STD file descriptors and redirect
00188   if (options.get_stdin () != ACE_INVALID_HANDLE) {
00189     if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
00190       ACE_OS::exit (errno);
00191     if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
00192       ACE_OS::exit (errno);
00193   }
00194   if (options.get_stdout () != ACE_INVALID_HANDLE) {
00195     if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
00196       ACE_OS::exit (errno);
00197     if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
00198       ACE_OS::exit (errno);
00199   }
00200   if (options.get_stderr () != ACE_INVALID_HANDLE) {
00201     if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
00202       ACE_OS::exit (errno);
00203     if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
00204       ACE_OS::exit (errno);
00205   }
00206 
00207   if (options.working_directory () != 0)
00208     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00209 
00210   this->child_id_ = vfork();
00211   if (this->child_id_ == 0) {
00212       ACE_OS::execvp (options.process_name (),
00213                 options.command_line_argv ());
00214       // something went wrong
00215       this->child_id_ = ACE_INVALID_PID;
00216   }
00217 
00218   // restore STD file descriptors (if necessary)
00219   if (options.get_stdin () != ACE_INVALID_HANDLE) {
00220     if (saved_stdin == -1)
00221       ACE_OS::close (ACE_STDIN);
00222     else
00223       ACE_OS::dup2 (saved_stdin, ACE_STDIN);
00224   }
00225   if (options.get_stdout () != ACE_INVALID_HANDLE) {
00226     if (saved_stdout == -1)
00227       ACE_OS::close (ACE_STDOUT);
00228     else
00229       ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
00230   }
00231   if (options.get_stderr () != ACE_INVALID_HANDLE) {
00232     if (saved_stderr == -1)
00233       ACE_OS::close (ACE_STDERR);
00234     else
00235       ACE_OS::dup2 (saved_stderr, ACE_STDERR);
00236   }
00237 
00238   return this->child_id_;
00239 #elif (defined (ACE_VXWORKS) && (ACE_VXWORKS > 0x600)) && defined (__RTP__)
00240   if (ACE_BIT_ENABLED (options.creation_flags (),
00241                        ACE_Process_Options::NO_EXEC))
00242     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00243 
00244   if (options.working_directory () != 0)
00245     ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00246 
00247   int saved_stdin = ACE_STDIN;
00248   int saved_stdout = ACE_STDOUT;
00249   int saved_stderr = ACE_STDERR;
00250   // Save STD file descriptors and redirect
00251   if (options.get_stdin () != ACE_INVALID_HANDLE) {
00252     if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF)
00253       ACE_OS::exit (errno);
00254     if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1)
00255       ACE_OS::exit (errno);
00256   }
00257   if (options.get_stdout () != ACE_INVALID_HANDLE) {
00258     if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF)
00259       ACE_OS::exit (errno);
00260     if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1)
00261       ACE_OS::exit (errno);
00262   }
00263   if (options.get_stderr () != ACE_INVALID_HANDLE) {
00264     if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF)
00265       ACE_OS::exit (errno);
00266     if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1)
00267       ACE_OS::exit (errno);
00268   }
00269 
00270   // Wide-char builds need narrow-char strings for commandline and
00271   // environment variables.
00272 # if defined (ACE_USES_WCHAR)
00273   wchar_t * const *wargv = options.command_line_argv ();
00274   size_t vcount, i;
00275   for (vcount = 0; wargv[vcount] != 0; ++vcount)
00276     ;
00277   char **procargv = new char *[vcount + 1];  // Need 0 at the end
00278   procargv[vcount] = 0;
00279   for (i = 0; i < vcount; ++i)
00280     procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00281 
00282   char **procenv = 0;
00283   if (options.inherit_environment ())
00284     {
00285       wargv = options.env_argv ();
00286       for (vcount = 0; wargv[vcount] != 0; ++vcount)
00287         ;
00288       procenv = new char *[vcount + 1];  // Need 0 at the end
00289       procenv[vcount] = 0;
00290       for (i = 0; i < vcount; ++i)
00291         procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00292     }
00293 # else
00294   const char **procargv = const_cast<const char**> (options.command_line_argv ());
00295   const char **procenv = const_cast<const char**> (options.env_argv ());
00296 # endif /* ACE_USES_WCHAR */
00297 
00298   this->child_id_ = ::rtpSpawn (procargv[0],
00299                                 procargv,
00300                                 procenv,
00301                                 200,          // priority
00302                                 0x10000,      // uStackSize
00303                                 0,            // options
00304                                 VX_FP_TASK);  // taskOptions
00305   int my_errno_ = errno;
00306   if (this->child_id_ == ERROR) {
00307       // something went wrong
00308       this->child_id_ = ACE_INVALID_PID;
00309   }
00310 
00311 # if defined (ACE_USES_WCHAR)
00312   if (procenv)
00313     delete procenv;
00314 # endif /* ACE_USES_WCHAR */
00315 
00316   // restore STD file descriptors (if necessary)
00317   if (options.get_stdin () != ACE_INVALID_HANDLE) {
00318     if (saved_stdin == -1)
00319       ACE_OS::close (ACE_STDIN);
00320     else
00321       ACE_OS::dup2 (saved_stdin, ACE_STDIN);
00322   }
00323   if (options.get_stdout () != ACE_INVALID_HANDLE) {
00324     if (saved_stdout == -1)
00325       ACE_OS::close (ACE_STDOUT);
00326     else
00327       ACE_OS::dup2 (saved_stdout, ACE_STDOUT);
00328   }
00329   if (options.get_stderr () != ACE_INVALID_HANDLE) {
00330     if (saved_stderr == -1)
00331       ACE_OS::close (ACE_STDERR);
00332     else
00333       ACE_OS::dup2 (saved_stderr, ACE_STDERR);
00334   }
00335 
00336   if (this->child_id_ == ACE_INVALID_PID) {
00337     errno = my_errno_;
00338   }
00339 
00340   return this->child_id_;
00341 #else /* ACE_WIN32 */
00342   // Fork the new process.
00343   this->child_id_ = ACE::fork (options.process_name (),
00344                                options.avoid_zombies ());
00345 
00346   if (this->child_id_ == 0)
00347     {
00348 # if !defined (ACE_LACKS_SETPGID)
00349       // If we're the child and the options specified a non-default
00350       // process group, try to set our pgid to it.  This allows the
00351       // <ACE_Process_Manager> to wait for processes by their
00352       // process-group.
00353       if (options.getgroup () != ACE_INVALID_PID
00354           && ACE_OS::setpgid (0,
00355                               options.getgroup ()) < 0)
00356         ACE_ERROR ((LM_ERROR,
00357                     ACE_TEXT ("%p.\n"),
00358                     ACE_TEXT ("ACE_Process::spawn: setpgid failed.")));
00359 # endif /* ACE_LACKS_SETPGID */
00360 
00361 # if !defined (ACE_LACKS_SETREGID)
00362       if (options.getrgid () != (uid_t) -1
00363           || options.getegid () != (uid_t) -1)
00364         if (ACE_OS::setregid (options.getrgid (),
00365                               options.getegid ()) == -1)
00366           ACE_ERROR ((LM_ERROR,
00367                       ACE_TEXT ("%p.\n"),
00368                       ACE_TEXT ("ACE_Process::spawn: setregid failed.")));
00369 # endif /* ACE_LACKS_SETREGID */
00370 
00371 # if !defined (ACE_LACKS_SETREUID)
00372       // Set user and group id's.
00373       if (options.getruid () != (uid_t) -1
00374           || options.geteuid () != (uid_t) -1)
00375         if (ACE_OS::setreuid (options.getruid (),
00376                               options.geteuid ()) == -1)
00377           ACE_ERROR ((LM_ERROR,
00378                       ACE_TEXT ("%p.\n"),
00379                       ACE_TEXT ("ACE_Process::spawn: setreuid failed.")));
00380 # endif /* ACE_LACKS_SETREUID */
00381 
00382       this->child (ACE_OS::getppid ());
00383     }
00384   else if (this->child_id_ != -1)
00385     this->parent (this->child_id_);
00386 
00387   // If we're not supposed to exec, return the process id.
00388   if (ACE_BIT_ENABLED (options.creation_flags (),
00389                        ACE_Process_Options::NO_EXEC))
00390     return this->child_id_;
00391 
00392   switch (this->child_id_)
00393     {
00394     case -1:
00395       // Error.
00396       return ACE_INVALID_PID;
00397     case 0:
00398       // Child process...exec the
00399       {
00400         if (options.get_stdin () != ACE_INVALID_HANDLE
00401             && ACE_OS::dup2 (options.get_stdin (),
00402                              ACE_STDIN) == -1)
00403           ACE_OS::exit (errno);
00404         else if (options.get_stdout () != ACE_INVALID_HANDLE
00405                  && ACE_OS::dup2 (options.get_stdout (),
00406                                   ACE_STDOUT) == -1)
00407           ACE_OS::exit (errno);
00408         else if (options.get_stderr () != ACE_INVALID_HANDLE
00409                  && ACE_OS::dup2 (options.get_stderr (),
00410                                   ACE_STDERR) == -1)
00411           ACE_OS::exit (errno);
00412 
00413         // close down unneeded descriptors
00414         ACE_OS::close (options.get_stdin ());
00415         ACE_OS::close (options.get_stdout ());
00416         ACE_OS::close (options.get_stderr ());
00417 
00418         // If we must, set the working directory for the child
00419         // process.
00420         if (options.working_directory () != 0)
00421           ACE_OS::chdir (options.working_directory ());
00422         // Should check for error here!
00423 
00424         // Child process executes the command.
00425         int result = 0;
00426 
00427         // Wide-char builds not on Windows need narrow-char strings for
00428         // exec() and environment variables. Don't need to worry about
00429         // releasing any of the converted string memory since this
00430         // process will either exec() or exit() shortly.
00431 # if defined (ACE_USES_WCHAR)
00432         ACE_Wide_To_Ascii n_procname (options.process_name ());
00433         const char *procname = n_procname.char_rep ();
00434 
00435         wchar_t * const *wargv = options.command_line_argv ();
00436         size_t vcount, i;
00437         for (vcount = 0; wargv[vcount] != 0; ++vcount)
00438           ;
00439         char **procargv = new char *[vcount + 1];  // Need 0 at the end
00440         procargv[vcount] = 0;
00441         for (i = 0; i < vcount; ++i)
00442           procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00443 
00444         wargv = options.env_argv ();
00445         for (vcount = 0; wargv[vcount] != 0; ++vcount)
00446           ;
00447         char **procenv = new char *[vcount + 1];  // Need 0 at the end
00448         procenv[vcount] = 0;
00449         for (i = 0; i < vcount; ++i)
00450           procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]);
00451 # else
00452         const char *procname = options.process_name ();
00453         char *const *procargv = options.command_line_argv ();
00454         char *const *procenv = options.env_argv ();
00455 # endif /* ACE_USES_WCHAR */
00456 
00457         if (options.inherit_environment ())
00458           {
00459             // Add the new environment variables to the environment
00460             // context of the context before doing an <execvp>.
00461             for (size_t i = 0; procenv[i] != 0; i++)
00462               if (ACE_OS::putenv (procenv[i]) != 0)
00463                 return ACE_INVALID_PID;
00464 
00465             // Now the forked process has both inherited variables and
00466             // the user's supplied variables.
00467             result = ACE_OS::execvp (procname, procargv);
00468           }
00469         else
00470           {
00471 # if defined (ghs)
00472             // GreenHills 1.8.8 (for VxWorks 5.3.x) can't compile this
00473             // code.  Processes aren't supported on VxWorks anyways.
00474             ACE_NOTSUP_RETURN (ACE_INVALID_PID);
00475 # else
00476             result = ACE_OS::execve (procname, procargv, procenv);
00477 # endif /* ghs */
00478           }
00479         if (result == -1)
00480           {
00481             // If the execv fails, this child needs to exit.
00482 
00483             // Exit with the errno so that the calling process can
00484             // catch this and figure out what went wrong.
00485             ACE_OS::_exit (errno);
00486           }
00487         // ... otherwise, this is never reached.
00488         return 0;
00489       }
00490     default:
00491       // Server process.  The fork succeeded.
00492       return this->child_id_;
00493     }
00494 #endif /* ACE_WIN32 */
00495 }
00496 
00497 void
00498 ACE_Process::parent (pid_t)
00499 {
00500   // nothing to do
00501 }
00502 
00503 void
00504 ACE_Process::child (pid_t)
00505 {
00506   // nothing to do
00507 }
00508 
00509 void
00510 ACE_Process::unmanage (void)
00511 {
00512   // nothing to do
00513 }
00514 
00515 int
00516 ACE_Process::running (void) const
00517 {
00518 #if defined (ACE_WIN32)
00519     DWORD code;
00520 
00521     BOOL result = ::GetExitCodeProcess (this->gethandle (),
00522                                         &code);
00523     return result && code == STILL_ACTIVE;
00524 #else
00525   if (ACE_INVALID_PID == this->getpid ())
00526     return 0;
00527   else
00528     return ACE_OS::kill (this->getpid (),
00529                          0) == 0
00530       || errno != ESRCH;
00531 #endif /* ACE_WIN32 */
00532 }
00533 
00534 pid_t
00535 ACE_Process::wait (const ACE_Time_Value &tv,
00536                    ACE_exitcode *status)
00537 {
00538 #if defined (ACE_WIN32)
00539   // Don't try to get the process exit status if wait failed so we can
00540   // keep the original error code intact.
00541   switch (::WaitForSingleObject (process_info_.hProcess,
00542                                  tv.msec ()))
00543     {
00544     case WAIT_OBJECT_0:
00545         // The error status of <GetExitCodeProcess> is nonetheless not
00546         // tested because we don't know how to return the value.
00547         ::GetExitCodeProcess (process_info_.hProcess,
00548                               &this->exit_code_);
00549       if (status != 0)
00550         *status = this->exit_code_;
00551       return this->getpid ();
00552     case WAIT_TIMEOUT:
00553       errno = ETIME;
00554       return 0;
00555     default:
00556       ACE_OS::set_errno_to_last_error ();
00557       return -1;
00558     }
00559 #elif defined(ACE_LACKS_UNIX_SIGNALS)
00560   if (tv == ACE_Time_Value::zero)
00561     {
00562       pid_t retv =
00563         ACE_OS::waitpid (this->child_id_,
00564                          &this->exit_code_,
00565                          WNOHANG);
00566       if (status != 0)
00567         *status = this->exit_code_;
00568 
00569       return retv;
00570     }
00571 
00572   if (tv == ACE_Time_Value::max_time)
00573 # if defined (ACE_VXWORKS)
00574     {
00575       pid_t retv;
00576       while ( (retv = this->wait (status)) == ACE_INVALID_PID && errno == EINTR ) ;
00577       return retv;
00578     }
00579 # else
00580      return this->wait (status);
00581 # endif
00582 
00583   pid_t pid = 0;
00584   ACE_Time_Value sleeptm (1);    // 1 msec
00585   if (sleeptm > tv)              // if sleeptime > waittime
00586       sleeptm = tv;
00587   ACE_Time_Value tmo (tv);       // Need one we can change
00588   for (ACE_Countdown_Time time_left (&tmo); tmo > ACE_Time_Value::zero ; time_left.update ())
00589     {
00590       pid = ACE_OS::waitpid (this->getpid (),
00591                              &this->exit_code_,
00592                              WNOHANG);
00593       if (status != 0)
00594         *status = this->exit_code_;
00595 
00596       if (pid > 0 || pid == ACE_INVALID_PID)
00597         break;          // Got a child or an error - all done
00598 
00599       // pid 0, nothing is ready yet, so wait.
00600       // Do a (very) short sleep (only this thread sleeps).
00601       ACE_OS::sleep (sleeptm);
00602     }
00603 
00604   return pid;
00605 #else /* !ACE_WIN32 && !ACE_LACKS_UNIX_SIGNALS */
00606   if (tv == ACE_Time_Value::zero)
00607     {
00608       pid_t retv =
00609         ACE_OS::waitpid (this->child_id_,
00610                          &this->exit_code_,
00611                          WNOHANG);
00612       if (status != 0)
00613         *status = this->exit_code_;
00614 
00615       return retv;
00616     }
00617 
00618   if (tv == ACE_Time_Value::max_time)
00619     return this->wait (status);
00620 
00621   // Need to wait but limited to specified time.
00622   // Force generation of SIGCHLD, even though we don't want to
00623   // catch it - just need it to interrupt the sleep below.
00624   // If this object has a reactor set, assume it was given at
00625   // open(), and there's already a SIGCHLD action set, so no
00626   // action is needed here.
00627   ACE_Sig_Action old_action;
00628   ACE_Sig_Action do_sigchld ((ACE_SignalHandler)sigchld_nop);
00629   do_sigchld.register_action (SIGCHLD, &old_action);
00630 
00631   pid_t pid;
00632   ACE_Time_Value tmo (tv);       // Need one we can change
00633   for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
00634     {
00635       pid = ACE_OS::waitpid (this->getpid (),
00636                              &this->exit_code_,
00637                              WNOHANG);
00638       if (status != 0)
00639         *status = this->exit_code_;
00640 
00641       if (pid > 0 || pid == ACE_INVALID_PID)
00642         break;          // Got a child or an error - all done
00643 
00644       // pid 0, nothing is ready yet, so wait.
00645       // Do a sleep (only this thread sleeps) til something
00646       // happens. This relies on SIGCHLD interrupting the sleep.
00647       // If SIGCHLD isn't delivered, we'll need to do something
00648       // with sigaction to force it.
00649       if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
00650         continue;
00651       // Timed out
00652       pid = 0;
00653       break;
00654     }
00655 
00656   // Restore the previous SIGCHLD action if it was changed.
00657   old_action.register_action (SIGCHLD);
00658 
00659   return pid;
00660 #endif /* ACE_WIN32 */
00661 }
00662 
00663 void
00664 ACE_Process::close_dup_handles (void)
00665 {
00666   if (this->dup_handles_.num_set () > 0)
00667     {
00668       ACE_Handle_Set_Iterator h_iter (this->dup_handles_);
00669       for (ACE_HANDLE h = h_iter ();
00670            h != ACE_INVALID_HANDLE;
00671            h = h_iter ())
00672         ACE_OS::closesocket (h);
00673       this->dup_handles_.reset ();
00674     }
00675   return;
00676 }
00677 
00678 void
00679 ACE_Process::close_passed_handles (void)
00680 {
00681   if (this->handles_passed_.num_set () > 0)
00682     {
00683       ACE_Handle_Set_Iterator h_iter (this->handles_passed_);
00684       for (ACE_HANDLE h = h_iter ();
00685            h != ACE_INVALID_HANDLE;
00686            h = h_iter ())
00687         ACE_OS::closesocket (h);
00688       this->handles_passed_.reset ();
00689     }
00690   return;
00691 }
00692 
00693 ACE_Process_Options::ACE_Process_Options (int ie,
00694                                           int cobl,
00695                                           int ebl,
00696                                           int mea)
00697   :
00698 #if !defined (ACE_HAS_WINCE)
00699     inherit_environment_ (ie),
00700 #endif /* ACE_HAS_WINCE */
00701     creation_flags_ (0),
00702     avoid_zombies_ (0),
00703 #if !defined (ACE_HAS_WINCE)
00704 #if defined (ACE_WIN32)
00705     environment_inherited_ (0),
00706     handle_inheritence_ (TRUE),
00707     process_attributes_ (0),
00708     thread_attributes_ (0),
00709 #else /* ACE_WIN32 */
00710     stdin_ (ACE_INVALID_HANDLE),
00711     stdout_ (ACE_INVALID_HANDLE),
00712     stderr_ (ACE_INVALID_HANDLE),
00713     ruid_ ((uid_t) -1),
00714     euid_ ((uid_t) -1),
00715     rgid_ ((uid_t) -1),
00716     egid_ ((uid_t) -1),
00717 #endif /* ACE_WIN32 */
00718     set_handles_called_ (0),
00719     environment_buf_index_ (0),
00720     environment_argv_index_ (0),
00721     environment_buf_ (0),
00722     environment_buf_len_ (ebl),
00723     max_environment_args_ (mea),
00724     max_environ_argv_index_ (mea - 1),
00725 #endif /* !ACE_HAS_WINCE */
00726     command_line_argv_calculated_ (0),
00727     command_line_buf_ (0),
00728     command_line_copy_ (0),
00729     command_line_buf_len_ (cobl),
00730     process_group_ (ACE_INVALID_PID)
00731 {
00732   ACE_NEW (command_line_buf_,
00733            ACE_TCHAR[cobl]);
00734   command_line_buf_[0] = '\0';
00735 
00736 #if !defined (ACE_HAS_WINCE)
00737   working_directory_[0] = '\0';
00738   ACE_NEW (environment_buf_,
00739            ACE_TCHAR[ebl]);
00740   ACE_NEW (environment_argv_,
00741            ACE_TCHAR *[mea]);
00742   environment_buf_[0] = '\0';
00743   environment_argv_[0] = 0;
00744   process_name_[0] = '\0';
00745 #if defined (ACE_WIN32)
00746   ACE_OS::memset ((void *) &this->startup_info_,
00747                   0,
00748                   sizeof this->startup_info_);
00749   this->startup_info_.cb = sizeof this->startup_info_;
00750 #endif /* ACE_WIN32 */
00751 #endif /* !ACE_HAS_WINCE */
00752 }
00753 
00754 #if !defined (ACE_HAS_WINCE)
00755 #if defined (ACE_WIN32)
00756 void
00757 ACE_Process_Options::inherit_environment (void)
00758 {
00759   // Ensure only once execution.
00760   if (environment_inherited_)
00761     return;
00762   environment_inherited_ = 1;
00763 
00764   // Get the existing environment.
00765   ACE_TCHAR *existing_environment = ACE_OS::getenvstrings ();
00766 
00767   size_t slot = 0;
00768 
00769   while (existing_environment[slot] != '\0')
00770     {
00771       size_t len = ACE_OS::strlen (existing_environment + slot);
00772 
00773       // Add the string to our env buffer.
00774       if (this->setenv_i (existing_environment + slot, len) == -1)
00775         {
00776           ACE_ERROR ((LM_ERROR,
00777                       ACE_TEXT ("%p.\n"),
00778                       ACE_TEXT ("ACE_Process_Options::ACE_Process_Options")));
00779           break;
00780         }
00781 
00782       // Skip to the next word.
00783       slot += len + 1;
00784     }
00785 
00786   ACE_TEXT_FreeEnvironmentStrings (existing_environment);
00787 }
00788 
00789 #else /* defined ACE_WIN32 */
00790 
00791 ACE_TCHAR * const *
00792 ACE_Process_Options::env_argv (void)
00793 {
00794   return environment_argv_;
00795 }
00796 
00797 #endif /* ACE_WIN32 */
00798 
00799 int
00800 ACE_Process_Options::setenv (ACE_TCHAR *envp[])
00801 {
00802   int i = 0;
00803   while (envp[i])
00804     {
00805       if (this->setenv_i (envp[i],
00806                           ACE_OS::strlen (envp[i])) == -1)
00807         return -1;
00808       i++;
00809     }
00810 
00811 #if defined (ACE_WIN32)
00812   if (inherit_environment_)
00813     this->inherit_environment ();
00814 #endif /* ACE_WIN32 */
00815 
00816   return 0;
00817 }
00818 
00819 int
00820 ACE_Process_Options::setenv (const ACE_TCHAR *format, ...)
00821 {
00822   ACE_TCHAR stack_buf[DEFAULT_COMMAND_LINE_BUF_LEN];
00823 
00824   // Start varargs.
00825   va_list argp;
00826   va_start (argp, format);
00827 
00828   // Add the rest of the varargs.
00829   ACE_OS::vsprintf (stack_buf,
00830                     format,
00831                     argp);
00832   // End varargs.
00833   va_end (argp);
00834 
00835   // Append the string to are environment buffer.
00836   if (this->setenv_i (stack_buf,
00837                       ACE_OS::strlen (stack_buf)) == -1)
00838     return -1;
00839 
00840 #if defined (ACE_WIN32)
00841   if (inherit_environment_)
00842     this->inherit_environment ();
00843 #endif /* ACE_WIN32 */
00844 
00845   return 0;
00846 }
00847 
00848 int
00849 ACE_Process_Options::setenv (const ACE_TCHAR *variable_name,
00850                              const ACE_TCHAR *format, ...)
00851 {
00852   // To address the potential buffer overflow,
00853   // we now allocate the buffer on heap with a variable size.
00854   size_t const buflen = ACE_OS::strlen (variable_name) + ACE_OS::strlen (format) + 2;
00855   ACE_TCHAR *newformat = 0;
00856   ACE_NEW_RETURN (newformat, ACE_TCHAR[buflen], -1);
00857   ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_newformat (newformat);
00858 
00859   // Add in the variable name.
00860   ACE_OS::sprintf (safe_newformat.get (),
00861                    ACE_TEXT ("%s=%s"),
00862                    variable_name,
00863                    format);
00864 
00865   // Start varargs.
00866   va_list argp;
00867   va_start (argp, format);
00868 
00869   // Add the rest of the varargs.
00870   size_t tmp_buflen = DEFAULT_COMMAND_LINE_BUF_LEN > buflen
00871                       ? static_cast<size_t> (DEFAULT_COMMAND_LINE_BUF_LEN) : buflen;
00872   int retval = 0;
00873 
00874   ACE_TCHAR *stack_buf = 0;
00875   ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
00876   ACE_Auto_Basic_Array_Ptr<ACE_TCHAR> safe_stack_buf (stack_buf);
00877 
00878   do
00879     {
00880       retval = ACE_OS::vsnprintf (safe_stack_buf.get (), tmp_buflen, safe_newformat.get (), argp);
00881       if (retval > ACE_Utils::truncate_cast<int> (tmp_buflen))
00882         {
00883           tmp_buflen *= 2;
00884           ACE_NEW_RETURN (stack_buf, ACE_TCHAR[tmp_buflen], -1);
00885           safe_stack_buf.reset (stack_buf);
00886         }
00887       else
00888         break;
00889     }
00890   while (1);
00891 
00892   if (retval == -1)
00893     {
00894       // In case that vsnprintf is not supported,
00895       // e.g., LynxOS and VxWorks 5, we have to
00896       // fall back to vsprintf.
00897       if (errno == ENOTSUP)
00898         {
00899           // ALERT: Since we have to use vsprintf here, there is still a chance that
00900           // the stack_buf overflows, i.e., the length of the resulting string
00901           // can still possibly go beyond the allocated stack_buf.
00902           retval = ACE_OS::vsprintf (safe_stack_buf.get (), safe_newformat.get (), argp);
00903           if (retval == -1)
00904             // vsprintf is failed.
00905             return -1;
00906         }
00907       else
00908         // vsnprintf is failed.
00909         return -1;
00910     }
00911 
00912   // End varargs.
00913   va_end (argp);
00914 
00915   // Append the string to our environment buffer.
00916   if (this->setenv_i (safe_stack_buf.get (),
00917                       ACE_OS::strlen (safe_stack_buf.get ())) == -1)
00918     return -1;
00919 
00920 #if defined (ACE_WIN32)
00921   if (inherit_environment_)
00922     this->inherit_environment ();
00923 #endif /* ACE_WIN32 */
00924 
00925   return 0;
00926 }
00927 
00928 int
00929 ACE_Process_Options::setenv_i (ACE_TCHAR *assignment,
00930                                size_t len)
00931 {
00932   // Add one for the null char.
00933   ++len;
00934 
00935   // If environment larger than allocated buffer return. Also check to
00936   // make sure we have enough room.
00937   if (environment_argv_index_ == max_environ_argv_index_
00938       || (len + environment_buf_index_) >= environment_buf_len_)
00939     return -1;
00940 
00941   // Copy the new environment string.
00942   ACE_OS::memcpy (environment_buf_ + environment_buf_index_,
00943                   assignment,
00944                   len * sizeof (ACE_TCHAR));
00945 
00946   // Update the argv array.
00947   environment_argv_[environment_argv_index_++] =
00948     environment_buf_ + environment_buf_index_;
00949   environment_argv_[environment_argv_index_] = 0;
00950 
00951   // Update our index.
00952   environment_buf_index_ += len;
00953 
00954   // Make sure the buffer is null-terminated.
00955   environment_buf_[environment_buf_index_] = '\0';
00956   return 0;
00957 }
00958 
00959 int
00960 ACE_Process_Options::set_handles (ACE_HANDLE std_in,
00961                                   ACE_HANDLE std_out,
00962                                   ACE_HANDLE std_err)
00963 {
00964   this->set_handles_called_ = 1;
00965 #if defined (ACE_WIN32)
00966 
00967   // Tell the new process to use our std handles.
00968   this->startup_info_.dwFlags = STARTF_USESTDHANDLES;
00969 
00970   if (std_in == ACE_INVALID_HANDLE)
00971     std_in = ACE_STDIN;
00972   if (std_out == ACE_INVALID_HANDLE)
00973     std_out = ACE_STDOUT;
00974   if (std_err == ACE_INVALID_HANDLE)
00975     std_err = ACE_STDERR;
00976 
00977   if (!::DuplicateHandle (::GetCurrentProcess (),
00978                           std_in,
00979                           ::GetCurrentProcess (),
00980                           &this->startup_info_.hStdInput,
00981                           0,
00982                           TRUE,
00983                           DUPLICATE_SAME_ACCESS))
00984     return -1;
00985 
00986   if (!::DuplicateHandle (::GetCurrentProcess (),
00987                           std_out,
00988                           ::GetCurrentProcess (),
00989                           &this->startup_info_.hStdOutput,
00990                           0,
00991                           TRUE,
00992                           DUPLICATE_SAME_ACCESS))
00993     return -1;
00994 
00995   if (!::DuplicateHandle (::GetCurrentProcess (),
00996                           std_err,
00997                           ::GetCurrentProcess (),
00998                           &this->startup_info_.hStdError,
00999                           0,
01000                           TRUE,
01001                           DUPLICATE_SAME_ACCESS))
01002     return -1;
01003 #else /* ACE_WIN32 */
01004   this->stdin_ = ACE_OS::dup (std_in);
01005   this->stdout_ = ACE_OS::dup (std_out);
01006   this->stderr_ = ACE_OS::dup (std_err);
01007 #endif /* ACE_WIN32 */
01008 
01009   return 0; // Success.
01010 }
01011 
01012 
01013 void
01014 ACE_Process_Options::release_handles ()
01015 {
01016   if (set_handles_called_)
01017     {
01018 #if defined (ACE_WIN32)
01019       ACE_OS::close (startup_info_.hStdInput);
01020       ACE_OS::close (startup_info_.hStdOutput);
01021       ACE_OS::close (startup_info_.hStdError);
01022 #else /* ACE_WIN32 */
01023       ACE_OS::close (stdin_);
01024       ACE_OS::close (stdout_);
01025       ACE_OS::close (stderr_);
01026 #endif /* ACE_WIN32 */
01027       set_handles_called_ = 0;
01028     }
01029 }
01030 #endif /* !ACE_HAS_WINCE */
01031 
01032 
01033 ACE_Process_Options::~ACE_Process_Options (void)
01034 {
01035 #if !defined (ACE_HAS_WINCE)
01036   release_handles();
01037   delete [] environment_buf_;
01038   delete [] environment_argv_;
01039 #endif /* !ACE_HAS_WINCE */
01040   delete [] command_line_buf_;
01041   ACE::strdelete (command_line_copy_);
01042 }
01043 
01044 int
01045 ACE_Process_Options::command_line (const ACE_TCHAR *const argv[])
01046 {
01047   // @@ Factor out the code between this
01048   int i = 0;
01049 
01050   if (argv[i])
01051     {
01052       ACE_OS::strcat (command_line_buf_, argv[i]);
01053       while (argv[++i])
01054         {
01055           ACE_OS::strcat (command_line_buf_,
01056                           ACE_TEXT (" "));
01057           ACE_OS::strcat (command_line_buf_,
01058                           argv[i]);
01059         }
01060     }
01061 
01062   command_line_argv_calculated_ = 0;
01063   return 0; // Success.
01064 }
01065 
01066 int
01067 ACE_Process_Options::command_line (const ACE_TCHAR *format, ...)
01068 {
01069   // Store all ... args in argp.
01070   va_list argp;
01071   va_start (argp, format);
01072 
01073   if (command_line_buf_len_ < 1)
01074     return -1;
01075 
01076 #if !defined (ACE_LACKS_VSNPRINTF) || defined (ACE_HAS_TRIO)
01077   // vsnprintf the format and args into command_line_buf__.
01078   ACE_OS::vsnprintf (command_line_buf_,
01079                      command_line_buf_len_,
01080                      format,
01081                      argp);
01082 #else
01083   // sprintf the format and args into command_line_buf__.
01084   ACE_OS::vsprintf (command_line_buf_,
01085                     format,
01086                     argp);
01087 #endif
01088 
01089   // Useless macro.
01090   va_end (argp);
01091 
01092   command_line_argv_calculated_ = 0;
01093   return 0;
01094 }
01095 
01096 #if defined (ACE_HAS_WCHAR) && !defined (ACE_HAS_WINCE)
01097 /**
01098  * @note Not available on Windows CE because it doesn't have a char version of
01099  * vsprintf.
01100  */
01101 int
01102 ACE_Process_Options::command_line (const ACE_ANTI_TCHAR *format, ...)
01103 {
01104   ACE_ANTI_TCHAR *anti_clb;
01105   ACE_NEW_RETURN (anti_clb,
01106                   ACE_ANTI_TCHAR[this->command_line_buf_len_],
01107                   -1);
01108 
01109   // Store all ... args in argp.
01110   va_list argp;
01111   va_start (argp, format);
01112 
01113   // sprintf the format and args into command_line_buf_.
01114   ACE_OS::vsprintf (anti_clb,
01115                     format,
01116                     argp);
01117 
01118   // Useless macro.
01119   va_end (argp);
01120 
01121   ACE_OS::strcpy (this->command_line_buf_,
01122                   ACE_TEXT_ANTI_TO_TCHAR (anti_clb));
01123 
01124   delete [] anti_clb;
01125 
01126   command_line_argv_calculated_ = 0;
01127   return 0;
01128 }
01129 #endif /* ACE_HAS_WCHAR && !ACE_HAS_WINCE */
01130 
01131 ACE_TCHAR *
01132 ACE_Process_Options::env_buf (void)
01133 {
01134 #if !defined (ACE_HAS_WINCE)
01135   if (environment_buf_[0] == '\0')
01136     return 0;
01137   else
01138     return environment_buf_;
01139 #else
01140   return 0;
01141 #endif /* !ACE_HAS_WINCE */
01142 }
01143 
01144 ACE_TCHAR * const *
01145 ACE_Process_Options::command_line_argv (void)
01146 {
01147   if (command_line_argv_calculated_ == 0)
01148     {
01149       command_line_argv_calculated_ = 1;
01150 
01151       // We need to free up any previous allocated memory first.
01152       ACE::strdelete (command_line_copy_);
01153 
01154       // We need to make a dynamically allocated copy here since
01155       // ACE_Tokenizer modifies its arguments.
01156       command_line_copy_ = ACE::strnew (command_line_buf_);
01157       // This tokenizer will replace all spaces with end-of-string
01158       // characters and will preserve text between "" and '' pairs.
01159       ACE_Tokenizer parser (command_line_copy_);
01160       parser.delimiter_replace (' ', '\0');
01161       parser.preserve_designators ('\"', '\"'); // "
01162       parser.preserve_designators ('\'', '\'');
01163 
01164       int x = 0;
01165       do
01166         command_line_argv_[x] = parser.next ();
01167       while (command_line_argv_[x] != 0
01168              // substract one for the ending zero.
01169              && ++x < MAX_COMMAND_LINE_OPTIONS - 1);
01170 
01171       command_line_argv_[x] = 0;
01172     }
01173 
01174   return command_line_argv_;
01175 }
01176 
01177 // Cause the specified handle to be passed to a child process
01178 // when it's spawned.
01179 int
01180 ACE_Process_Options::pass_handle (ACE_HANDLE h)
01181 {
01182 # if defined (ACE_WIN32)
01183 #  if defined (ACE_HAS_WINCE)
01184   ACE_NOTSUP_RETURN (-1);
01185 #  else
01186 
01187   // This is oriented towards socket handles... may need some adjustment
01188   // for non-sockets.
01189   // This is all based on an MSDN article:
01190   // http://support.microsoft.com/support/kb/articles/Q150/5/23.asp
01191   // If on Win95/98, the handle needs to be duplicated for the to-be-spawned
01192   // process. On WinNT, they get inherited by the child process automatically.
01193   // If the handle is duplicated, remember the duplicate so it can be
01194   // closed later. Can't be closed now, or the child won't get it.
01195   ACE_TEXT_OSVERSIONINFO osvi;
01196   ZeroMemory (&osvi, sizeof (osvi));
01197   osvi.dwOSVersionInfoSize = sizeof (ACE_TEXT_OSVERSIONINFO);
01198   // If this is Win95/98 or we can't tell, duplicate the handle.
01199   if (!ACE_TEXT_GetVersionEx (&osvi) || osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
01200     {
01201       HANDLE dup_handle;
01202       if (!DuplicateHandle (GetCurrentProcess (),
01203                             static_cast<HANDLE> (h),
01204                             GetCurrentProcess (),
01205                             &dup_handle,
01206                             0,
01207                             TRUE,   // Inheritable
01208                             DUPLICATE_SAME_ACCESS))
01209         return -1;
01210       dup_handles_.set_bit (static_cast<ACE_HANDLE> (dup_handle));
01211     }
01212 #  endif /* ACE_HAS_WINCE */
01213 #endif /* ACE_WIN32 */
01214 
01215   this->handles_passed_.set_bit (h);
01216 
01217   return 0;
01218 }
01219 
01220 // Get a copy of the handles the ACE_Process_Options duplicated
01221 // for the spawned process.
01222 int
01223 ACE_Process_Options::dup_handles (ACE_Handle_Set &set) const
01224 {
01225   if (this->dup_handles_.num_set () == 0)
01226     return 0;
01227   set.reset ();
01228   set = this->dup_handles_;
01229   return 1;
01230 }
01231 
01232 // Get a copy of the handles passed to the spawned process. This
01233 // will be the set of handles previously passed to @arg pass_handle().
01234 int
01235 ACE_Process_Options::passed_handles (ACE_Handle_Set &set) const
01236 {
01237   if (this->handles_passed_.num_set () == 0)
01238     return 0;
01239   set.reset ();
01240   set = this->handles_passed_;
01241   return 1;
01242 }
01243 
01244 ACE_Managed_Process::~ACE_Managed_Process (void)
01245 {
01246 }
01247 
01248 void
01249 ACE_Managed_Process::unmanage (void)
01250 {
01251   delete this;
01252 }
01253 
01254 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 12:05:35 2008 for ACE by doxygen 1.3.6