8274320: os::fork_and_exec() should be using posix_spawn
Reviewed-by: mdoerr, dholmes
This commit is contained in:
parent
bf2e9ee9d3
commit
158831e4c3
@ -60,6 +60,7 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <spawn.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/times.h>
|
#include <sys/times.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -1955,40 +1956,16 @@ char** os::get_environ() { return environ; }
|
|||||||
// doesn't block SIGINT et al.
|
// doesn't block SIGINT et al.
|
||||||
// -this function is unsafe to use in non-error situations, mainly
|
// -this function is unsafe to use in non-error situations, mainly
|
||||||
// because the child process will inherit all parent descriptors.
|
// because the child process will inherit all parent descriptors.
|
||||||
int os::fork_and_exec(const char* cmd, bool prefer_vfork) {
|
int os::fork_and_exec(const char* cmd) {
|
||||||
const char * argv[4] = {"sh", "-c", cmd, NULL};
|
const char* argv[4] = {"sh", "-c", cmd, NULL};
|
||||||
|
pid_t pid = -1;
|
||||||
pid_t pid ;
|
|
||||||
|
|
||||||
char** env = os::get_environ();
|
char** env = os::get_environ();
|
||||||
|
// Note: cast is needed because posix_spawn() requires - for compatibility with ancient
|
||||||
// Use always vfork on AIX, since its safe and helps with analyzing OOM situations.
|
// C-code - a non-const argv/envp pointer array. But it is fine to hand in literal
|
||||||
// Otherwise leave it up to the caller.
|
// strings and just cast the constness away. See also ProcessImpl_md.c.
|
||||||
AIX_ONLY(prefer_vfork = true;)
|
int rc = ::posix_spawn(&pid, "/bin/sh", NULL, NULL, (char**) argv, env);
|
||||||
#ifdef __APPLE__
|
if (rc == 0) {
|
||||||
pid = ::fork();
|
|
||||||
#else
|
|
||||||
pid = prefer_vfork ? ::vfork() : ::fork();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (pid < 0) {
|
|
||||||
// fork failed
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
} else if (pid == 0) {
|
|
||||||
// child process
|
|
||||||
|
|
||||||
::execve("/bin/sh", (char* const*)argv, env);
|
|
||||||
|
|
||||||
// execve failed
|
|
||||||
::_exit(-1);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// copied from J2SE ..._waitForProcessExit() in UNIXProcess_md.c; we don't
|
|
||||||
// care about the actual exit code, for now.
|
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
// Wait for the child process to exit. This returns immediately if
|
// Wait for the child process to exit. This returns immediately if
|
||||||
// the child has already exited. */
|
// the child has already exited. */
|
||||||
while (::waitpid(pid, &status, 0) < 0) {
|
while (::waitpid(pid, &status, 0) < 0) {
|
||||||
@ -1998,7 +1975,6 @@ int os::fork_and_exec(const char* cmd, bool prefer_vfork) {
|
|||||||
default: return -1;
|
default: return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
// The child exited normally; get its exit code.
|
// The child exited normally; get its exit code.
|
||||||
return WEXITSTATUS(status);
|
return WEXITSTATUS(status);
|
||||||
@ -2013,6 +1989,9 @@ int os::fork_and_exec(const char* cmd, bool prefer_vfork) {
|
|||||||
// Unknown exit code; pass it through
|
// Unknown exit code; pass it through
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Don't log, we are inside error handling
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5624,7 +5624,7 @@ int os::PlatformMonitor::wait(jlong millis) {
|
|||||||
|
|
||||||
// Run the specified command in a separate process. Return its exit value,
|
// Run the specified command in a separate process. Return its exit value,
|
||||||
// or -1 on failure (e.g. can't create a new process).
|
// or -1 on failure (e.g. can't create a new process).
|
||||||
int os::fork_and_exec(const char* cmd, bool dummy /* ignored */) {
|
int os::fork_and_exec(const char* cmd) {
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
DWORD exit_code;
|
DWORD exit_code;
|
||||||
|
@ -515,10 +515,7 @@ class os: AllStatic {
|
|||||||
|
|
||||||
// run cmd in a separate process and return its exit code; or -1 on failures.
|
// run cmd in a separate process and return its exit code; or -1 on failures.
|
||||||
// Note: only safe to use in fatal error situations.
|
// Note: only safe to use in fatal error situations.
|
||||||
// The "prefer_vfork" argument is only used on POSIX platforms to
|
static int fork_and_exec(const char *cmd);
|
||||||
// indicate whether vfork should be used instead of fork to spawn the
|
|
||||||
// child process (ignored on AIX, which always uses vfork).
|
|
||||||
static int fork_and_exec(const char *cmd, bool prefer_vfork = false);
|
|
||||||
|
|
||||||
// Call ::exit() on all platforms
|
// Call ::exit() on all platforms
|
||||||
static void exit(int num);
|
static void exit(int num);
|
||||||
|
@ -1788,7 +1788,7 @@ void VM_ReportJavaOutOfMemory::doit() {
|
|||||||
#endif
|
#endif
|
||||||
tty->print_cr("\"%s\"...", cmd);
|
tty->print_cr("\"%s\"...", cmd);
|
||||||
|
|
||||||
if (os::fork_and_exec(cmd, true) < 0) {
|
if (os::fork_and_exec(cmd) < 0) {
|
||||||
tty->print_cr("os::fork_and_exec failed: %s (%s=%d)",
|
tty->print_cr("os::fork_and_exec failed: %s (%s=%d)",
|
||||||
os::strerror(errno), os::errno_name(errno), errno);
|
os::strerror(errno), os::errno_name(errno), errno);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user