#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(). |
1.3.6