Process.cpp

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

Generated on Tue Feb 2 17:18:41 2010 for ACE by  doxygen 1.4.7