Process.cpp

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

Generated on Thu Nov 9 09:42:00 2006 for ACE by doxygen 1.3.6