--- old/src/hotspot/os/linux/os_linux.cpp 2018-09-13 12:39:21.277026957 +0530 +++ new/src/hotspot/os/linux/os_linux.cpp 2018-09-13 12:39:21.089026958 +0530 @@ -5767,6 +5767,61 @@ } } + +// Run the specified command in a separate process. Return its exit value, +// or -1 on failure (e.g. can't fork a new process). +// Unlike system(), this function can be called from signal handler. It +// doesn't block SIGINT et al. +int os::vfork_and_exec(char* cmd) { + const char * argv[4] = {"sh", "-c", cmd, NULL}; + + pid_t pid = vfork(); + + if (pid < 0) { + // fork failed + return -1; + + } else if (pid == 0) { + // child process + + execve("/bin/sh", (char* const*)argv, environ); + + // 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; + + // Wait for the child process to exit. This returns immediately if + // the child has already exited. */ + while (waitpid(pid, &status, 0) < 0) { + switch (errno) { + case ECHILD: return 0; + case EINTR: break; + default: return -1; + } + } + + if (WIFEXITED(status)) { + // The child exited normally; get its exit code. + return WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + // The child exited because of a signal + // The best value to return is 0x80 + signal number, + // because that is what all Unix shells do, and because + // it allows callers to distinguish between process exit and + // process death by signal. + return 0x80 + WTERMSIG(status); + } else { + // Unknown exit code; pass it through + return status; + } + } +} + // Get the default path to the core file // Returns the length of the string int os::get_core_path(char* buffer, size_t bufferSize) { --- old/src/hotspot/share/runtime/os.hpp 2018-09-13 12:39:21.637026956 +0530 +++ new/src/hotspot/share/runtime/os.hpp 2018-09-13 12:39:21.517026956 +0530 @@ -539,7 +539,9 @@ // run cmd in a separate process and return its exit code; or -1 on failures static int fork_and_exec(char *cmd); - +#if defined(LINUX) + static int vfork_and_exec(char *cmd); +#endif // Call ::exit() on all platforms but Windows static void exit(int num); --- old/src/hotspot/share/utilities/vmError.cpp 2018-09-13 12:39:21.965026954 +0530 +++ new/src/hotspot/share/utilities/vmError.cpp 2018-09-13 12:39:21.841026955 +0530 @@ -1562,7 +1562,11 @@ #endif tty->print_cr("\"%s\"...", cmd); +#if defined(LINUX) + if (os::vfork_and_exec(cmd) < 0) { +#else if (os::fork_and_exec(cmd) < 0) { +#endif tty->print_cr("os::fork_and_exec failed: %s (%s=%d)", os::strerror(errno), os::errno_name(errno), errno); }