#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 440 of file Process.h.
|
Default construction. Must use <ACE_Process::spawn> to start.
Definition at line 41 of file Process.cpp. References ACE_INVALID_PID, and ACE_OS::memset().
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 } |
|
Destructor.
Definition at line 55 of file Process.cpp. References ACE_OS::close(), and close_dup_handles().
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 } |
|
|
|
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 494 of file Process.cpp. References pid_t. Referenced by spawn().
00495 {
00496 // nothing to do
00497 }
|
|
Close all the handles in the set obtained from the
Definition at line 654 of file Process.cpp. References ACE_OS::closesocket(), ACE_Handle_Set::num_set(), and ACE_Handle_Set::reset(). Referenced by ~ACE_Process().
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 } |
|
Close all the handles in the set obtained from the
Definition at line 669 of file Process.cpp. References ACE_OS::closesocket(), ACE_Handle_Set::num_set(), and ACE_Handle_Set::reset().
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 } |
|
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 488 of file Process.cpp. References pid_t. Referenced by spawn().
00489 {
00490 // nothing to do
00491 }
|
|
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 68 of file Process.cpp. Referenced by spawn().
00069 {
00070 return 0;
00071 }
|
|
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 506 of file Process.cpp. References ACE_INVALID_PID, gethandle(), getpid(), and ACE_OS::kill().
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 } |
|
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 74 of file Process.cpp. References ACE_OS::_exit(), ACE_BIT_ENABLED, ACE_ERROR, ACE_INVALID_PID, ACE_LIB_TEXT, ACE_NOTSUP_RETURN, ACE_STDERR, ACE_STDIN, ACE_STDOUT, ACE_TCHAR, ACE_Process_Options::avoid_zombies(), ACE_OS::chdir(), child(), ACE_OS::close(), ACE_Process_Options::command_line_argv(), ACE_Process_Options::command_line_buf(), ACE_Process_Options::creation_flags(), ACE_OS::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().
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 } |
|
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 500 of file Process.cpp. Referenced by ACE_Process_Manager::remove_proc().
00501 {
00502 // nothing to do
00503 }
|
|
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 525 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.
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 } |
|
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 570 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 565 of file Process.h. Referenced by gethandle(), process_info(), spawn(), and wait(). |