# HG changeset patch # User dholmes # Date 1430350630 14400 # Node ID 915ca3e9d15e6b6c71a51a5035c187f80fd09edb # Parent 99edc344d77c8b108be1d579f34289a975534fd2 8078470: [Linux] Replace syscall use in os::fork_and_exec with glibc fork() and execve() Reviewed-by: stuefe, dsamersoff, dcubed diff -r 99edc344d77c -r 915ca3e9d15e src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Tue Apr 14 18:11:06 2015 +0300 +++ b/src/os/linux/vm/os_linux.cpp Wed Apr 29 19:37:10 2015 -0400 @@ -5929,14 +5929,6 @@ extern char** environ; -#ifndef __NR_fork -#define __NR_fork IA32_ONLY(2) IA64_ONLY(not defined) AMD64_ONLY(57) -#endif - -#ifndef __NR_execve -#define __NR_execve IA32_ONLY(11) IA64_ONLY(1033) AMD64_ONLY(59) -#endif - // 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 @@ -5944,13 +5936,7 @@ int os::fork_and_exec(char* cmd) { const char * argv[4] = {"sh", "-c", cmd, NULL}; - // fork() in LinuxThreads/NPTL is not async-safe. It needs to run - // pthread_atfork handlers and reset pthread library. All we need is a - // separate process to execve. Make a direct syscall to fork process. - // On IA64 there's no fork syscall, we have to use fork() and hope for - // the best... - pid_t pid = NOT_IA64(syscall(__NR_fork);) - IA64_ONLY(fork();) + pid_t pid = fork(); if (pid < 0) { // fork failed @@ -5959,15 +5945,7 @@ } else if (pid == 0) { // child process - // execve() in LinuxThreads will call pthread_kill_other_threads_np() - // first to kill every thread on the thread list. Because this list is - // not reset by fork() (see notes above), execve() will instead kill - // every thread in the parent process. We know this is the only thread - // in the new process, so make a system call directly. - // IA64 should use normal execve() from glibc to match the glibc fork() - // above. - NOT_IA64(syscall(__NR_execve, "/bin/sh", argv, environ);) - IA64_ONLY(execve("/bin/sh", (char* const*)argv, environ);) + execve("/bin/sh", (char* const*)argv, environ); // execve failed _exit(-1); diff -r 99edc344d77c -r 915ca3e9d15e src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Tue Apr 14 18:11:06 2015 +0300 +++ b/src/share/vm/utilities/vmError.cpp Wed Apr 29 19:37:10 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1013,7 +1013,9 @@ out.print_raw (cmd); out.print_raw_cr("\" ..."); - os::fork_and_exec(cmd); + if (os::fork_and_exec(cmd) < 0) { + out.print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno); + } } // done with OnError @@ -1098,7 +1100,9 @@ #endif tty->print_cr("\"%s\"...", cmd); - os::fork_and_exec(cmd); + if (os::fork_and_exec(cmd) < 0) { + tty->print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno); + } } } diff -r 99edc344d77c -r 915ca3e9d15e test/runtime/ErrorHandling/TestOnError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/ErrorHandling/TestOnError.java Wed Apr 29 19:37:10 2015 -0400 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestOnError + * @summary Test using -XX:OnError= + * @library /testlibrary + * @build TestOnError com.oracle.java.testlibrary.* + * @run main TestOnError + * @bug 8078470 + */ + +import com.oracle.java.testlibrary.*; + +public class TestOnError { + + public static void main(String[] args) throws Exception { + if (!Platform.isDebugBuild()) { + System.out.println("Test requires a non-product build - skipping"); + return; + } + + String msg = "Test Succeeded"; + + // Execute the VM so that a + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:-TransmitErrorReport", + "-XX:ErrorHandlerTest=12", // trigger potential SEGV + "-XX:OnError=echo " + msg, + TestOnError.class.getName()); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + /* Actual output will include: + # + # -XX:OnError="echo Test Succeeded" + # Executing /bin/sh -c "echo Test Succeeded"... + Test Succeeded + + So we don't want to match on the "# Executing ..." line, and they + both get written to stdout. + */ + output.stdoutShouldMatch("^" + msg); // match start of line only + System.out.println("PASSED"); + } +} diff -r 99edc344d77c -r 915ca3e9d15e test/runtime/ErrorHandling/TestOnOutOfMemoryError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/ErrorHandling/TestOnOutOfMemoryError.java Wed Apr 29 19:37:10 2015 -0400 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestOnOutOfMemoryError + * @summary Test using -XX:OnOutOfMemoryError= + * @library /testlibrary + * @build TestOnOutOfMemoryError com.oracle.java.testlibrary.* + * @run main TestOnOutOfMemoryError + * @bug 8078470 + */ + +import com.oracle.java.testlibrary.*; + +public class TestOnOutOfMemoryError { + + public static void main(String[] args) throws Exception { + if (args.length == 1) { + // This should guarantee to throw: + // java.lang.OutOfMemoryError: Requested array size exceeds VM limit + Object[] oa = new Object[Integer.MAX_VALUE]; + return; + } + + // else this is the main test + String msg = "Test Succeeded"; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:OnOutOfMemoryError=echo " + msg, + TestOnOutOfMemoryError.class.getName(), + "throwOOME"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + /* Actual output should look like this: + # + # java.lang.OutOfMemoryError: Requested array size exceeds VM limit + # -XX:OnOutOfMemoryError="echo Test Succeeded" + # Executing /bin/sh -c "echo Test Succeeded"... + Test Succeeded + Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit + at OOME.main(OOME.java:3) + + So we don't want to match on the "# Executing ..." line, and they + both get written to stdout. + */ + output.shouldContain("Requested array size exceeds VM limit"); + output.stdoutShouldMatch("^" + msg); // match start of line only + System.out.println("PASSED"); + } +}