#include <Process.h>
Inheritance diagram for ACE_Process:
Public Member Functions | |
ACE_Process (void) | |
Default construction. Must use <ACE_Process::spawn> to start. | |
virtual | ~ACE_Process (void) |
Destructor. | |
virtual int | prepare (ACE_Process_Options &options) |
virtual pid_t | spawn (ACE_Process_Options &options) |
virtual void | parent (pid_t child) |
virtual void | child (pid_t parent) |
virtual void | unmanage (void) |
pid_t | wait (ACE_exitcode *status=0, int wait_options=0) |
pid_t | wait (const ACE_Time_Value &tv, ACE_exitcode *status=0) |
int | kill (int signum=SIGINT) |
int | terminate (void) |
pid_t | getpid (void) const |
Return the process id of the new child process. | |
ACE_HANDLE | gethandle (void) const |
Return the handle of the process, if it has one. | |
int | running (void) const |
Return 1 if running; 0 otherwise. | |
ACE_exitcode | exit_code (void) const |
int | return_value (void) const |
void | close_dup_handles (void) |
void | close_passed_handles (void) |
PROCESS_INFORMATION | process_info (void) |
Protected Member Functions | |
void | exit_code (ACE_exitcode code) |
Protected Attributes | |
PROCESS_INFORMATION | process_info_ |
ACE_exitcode | exit_code_ |
ACE_Handle_Set | handles_passed_ |
Set of handles that were passed to the child process. | |
ACE_Handle_Set | dup_handles_ |
Handle duplicates made for the child process. | |
Private Member Functions | |
ACE_Process (const ACE_Process &) | |
void | operator= (const ACE_Process &) |
Friends | |
class | ACE_Process_Manager |
A Portable encapsulation for creating new processes. Notice that on UNIX platforms, if the is used, the is using the system call. It means that the should include a full path to the program file ( does not search the PATH). If is not used then, the is using the which searches for the program file in the PATH variable.
Definition at line 447 of file Process.h.
|
Default construction. Must use <ACE_Process::spawn> to start.
Definition at line 45 of file Process.cpp. References ACE_INVALID_PID, and ACE_OS::memset().
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 } |
|
Destructor.
Definition at line 59 of file Process.cpp. References ACE_OS::close(), and close_dup_handles().
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 } |
|
|
|
Called just after <ACE_OS::fork> in the child's context. The default does nothing. This function is *not* called on Win32 because the process-creation scheme does not allow it. Definition at line 504 of file Process.cpp. References pid_t. Referenced by spawn().
00505 {
00506 // nothing to do
00507 }
|
|
Close all the handles in the set obtained from the
Definition at line 664 of file Process.cpp. References ACE_OS::closesocket(), ACE_Handle_Set::num_set(), and ACE_Handle_Set::reset(). Referenced by ~ACE_Process().
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 } |
|
Close all the handles in the set obtained from the
Definition at line 679 of file Process.cpp. References ACE_OS::closesocket(), ACE_Handle_Set::num_set(), and ACE_Handle_Set::reset().
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 } |
|
Set this process' . ACE_Process_Manager uses this method to set the after successfully waiting for this process to exit. Definition at line 96 of file Process.inl. References ACE_exitcode, and exit_code_.
00097 { 00098 this->exit_code_ = code; 00099 } |
|
Return the Process' exit code. This method returns the raw exit status returned from system APIs (such as or ). This value is system dependent. Definition at line 90 of file Process.inl. References exit_code_. Referenced by ACE_Process_Manager::notify_proc_handler().
00091 { 00092 return this->exit_code_; 00093 } |
|
Return the handle of the process, if it has one.
Definition at line 23 of file Process.inl. References process_info_. Referenced by ACE_Process_Manager::append_proc(), ACE_Process_Manager::find_proc(), ACE_Process_Manager::remove_proc(), running(), and ACE_Process_Manager::wait().
00024 { 00025 #if defined (ACE_WIN32) 00026 return process_info_.hProcess; 00027 #else 00028 return ACE_HANDLE (child_id_); 00029 #endif /* ACE_WIN32 */ 00030 } |
|
Return the process id of the new child process.
Definition at line 33 of file Process.inl. Referenced by ACE_Process_Manager::find_proc(), ACE_Process_Manager::handle_signal(), ACE_Process_Manager::insert_proc(), kill(), running(), ACE_Process_Manager::set_scheduler_all(), spawn(), terminate(), ACE_Process_Manager::wait(), and wait().
00035 { 00036 #if defined (ACE_WIN32) 00037 return process_info_.dwProcessId; 00038 #else /* ACE_WIN32 */ 00039 return child_id_; 00040 #endif /* ACE_WIN32 */ 00041 } |
|
Send the process a signal. This is only portable to operating systems that support signals, such as UNIX/POSIX. Definition at line 62 of file Process.inl. References getpid(), and ACE_OS::kill().
00063 { 00064 if (this->getpid () != -1) 00065 return ACE_OS::kill (this->getpid (), signum); 00066 else 00067 return -1; 00068 } |
|
|
|
Called just after <ACE_OS::fork> in the parent's context, if the succeeds. The default is to do nothing. Definition at line 498 of file Process.cpp. References pid_t. Referenced by spawn().
00499 {
00500 // nothing to do
00501 }
|
|
Called just before <ACE_OS::fork> in the . If this returns non-zero, the is aborted (and returns ACE_INVALID_PID). The default simply returns zero. Definition at line 72 of file Process.cpp. Referenced by spawn().
00073 {
00074 return 0;
00075 }
|
|
Definition at line 16 of file Process.inl. References process_info_.
00017 { 00018 return process_info_; 00019 } |
|
Return the Process' return value. This method returns the actual return value that a child process returns or s. Definition at line 80 of file Process.inl. References exit_code_, and WEXITSTATUS.
00081 { 00082 #if defined (ACE_WIN32) 00083 return this->exit_code_; 00084 #else 00085 return WEXITSTATUS (this->exit_code_); 00086 #endif /* ACE_WIN32 */ 00087 } |
|
Return 1 if running; 0 otherwise.
Definition at line 516 of file Process.cpp. References ACE_INVALID_PID, gethandle(), getpid(), and ACE_OS::kill().
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 } |
|
Launch a new process as described by options. On success, returns 1 if the option avoid_zombies is set, else returns the process id of the newly spawned child. Returns -1 on failure. This will be fixed in the future versions of ACE when the process id of the child will be returned regardless of the option. Definition at line 78 of file Process.cpp. References ACE_OS::_exit(), ACE_BIT_ENABLED, ACE_ERROR, ACE_INVALID_PID, ACE_NOTSUP_RETURN, ACE_STDERR, ACE_STDIN, ACE_STDOUT, ACE_TCHAR, ACE_TEXT, ACE_TEXT_CreateProcess, ACE_Process_Options::avoid_zombies(), ACE_Wide_To_Ascii::char_rep(), ACE_OS::chdir(), child(), ACE_OS::close(), ACE_Process_Options::command_line_argv(), ACE_Process_Options::command_line_buf(), ACE_Wide_To_Ascii::convert(), ACE_Process_Options::creation_flags(), ACE_OS::dup(), ACE_OS::dup2(), ACE_Process_Options::dup_handles(), ACE_Process_Options::env_buf(), ACE_OS::execve(), ACE_OS::execvp(), ACE_OS::exit(), ACE::fork(), ACE_Process_Options::get_process_attributes(), ACE_Process_Options::get_thread_attributes(), ACE_Process_Options::getgroup(), getpid(), ACE_Process_Options::handle_inheritence(), ACE_Process_Options::inherit_environment(), LM_ERROR, parent(), ACE_Process_Options::passed_handles(), prepare(), process_info_, ACE_Process_Options::process_name(), ACE_OS::putenv(), ACE_OS::setpgid(), ACE_OS::setregid(), ACE_OS::setreuid(), ACE_OS::sprintf(), ACE_Process_Options::startup_info(), ACE_OS::strlen(), uid_t, and ACE_Process_Options::working_directory(). Referenced by ACE_Process_Manager::spawn().
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 } |
|
Terminate the process abruptly using <ACE::terminate_process>. This call doesn't give the process a chance to cleanup, so use it with caution... Definition at line 71 of file Process.inl. References getpid(), and ACE::terminate_process().
00072 { 00073 if (this->getpid () != -1) 00074 return ACE::terminate_process (this->getpid ()); 00075 else 00076 return -1; 00077 } |
|
Called by a that is removing this Process from its table of managed Processes. Default is to do nothing. Reimplemented in ACE_Managed_Process. Definition at line 510 of file Process.cpp. Referenced by ACE_Process_Manager::remove_proc().
00511 {
00512 // nothing to do
00513 }
|
|
Timed wait for the process we've created to exit. A return value of -1 indicates that the something failed; 0 indicates that a timeout occurred. Otherwise, the child's process id is returned. If != 0, it points to an integer where the function stores the child's exit status.
Definition at line 535 of file Process.cpp. References ACE_exitcode, ACE_INVALID_PID, ACE_SignalHandler, ETIME, exit_code_, getpid(), ACE_Time_Value::msec(), pid_t, process_info_, ACE_Sig_Action::register_action(), ACE_OS::set_errno_to_last_error(), SIGCHLD, ACE_OS::sleep(), ACE_Countdown_Time::update(), wait(), ACE_OS::waitpid(), and WNOHANG.
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 } |
|
Wait for the process we've created to exit. If != 0, it points to an integer where the function store the exit status of child process to. If == then return 0 and don't block if the child process hasn't exited yet. A return value of -1 represents the operation failed, otherwise, the child process id is returned. Definition at line 44 of file Process.inl. References ACE_exitcode, exit_code_, pid_t, process_info_, and ACE_OS::wait(). Referenced by ACE_Process_Manager::wait(), and wait().
00046 { 00047 pid_t retv = 00048 ACE_OS::wait (this->getpid (), 00049 &this->exit_code_, 00050 wait_options 00051 #if defined (ACE_WIN32) 00052 , process_info_.hProcess 00053 #endif /* ACE_WIN32 */ 00054 ); 00055 if (status != 0) 00056 *status = this->exit_code_; 00057 00058 return retv; 00059 } |
|
|
|
Handle duplicates made for the child process.
|
|
Definition at line 577 of file Process.h. Referenced by exit_code(), return_value(), and wait(). |
|
Set of handles that were passed to the child process.
|
|
Definition at line 572 of file Process.h. Referenced by gethandle(), process_info(), spawn(), and wait(). |