diff --git a/src/java.base/unix/classes/java/lang/ProcessImpl.java b/src/java.base/unix/classes/java/lang/ProcessImpl.java index 390a4f284774a..c647deb634c5d 100644 --- a/src/java.base/unix/classes/java/lang/ProcessImpl.java +++ b/src/java.base/unix/classes/java/lang/ProcessImpl.java @@ -82,8 +82,7 @@ final class ProcessImpl extends Process { private static enum LaunchMechanism { // order IS important! FORK, - POSIX_SPAWN, - VFORK + POSIX_SPAWN } /** @@ -98,29 +97,15 @@ private static LaunchMechanism launchMechanism() { try { // Should be value of a LaunchMechanism enum - LaunchMechanism lm = LaunchMechanism.valueOf(s.toUpperCase(Locale.ROOT)); - switch (OperatingSystem.current()) { - case LINUX: { - // All options are valid for Linux, but VFORK is deprecated and results - // in a warning - if (lm == LaunchMechanism.VFORK) { - System.err.println("VFORK MODE DEPRECATED"); - System.err.println(""" - The VFORK launch mechanism has been deprecated for being dangerous. - It will be removed in a future java version. Either remove the - jdk.lang.Process.launchMechanism property (preferred) or use FORK mode - instead (-Djdk.lang.Process.launchMechanism=FORK). - """); - } - return lm; - } - case AIX: - case MACOS: - if (lm != LaunchMechanism.VFORK) { - return lm; // All but VFORK are valid - } - break; + String launchMechanism = s.toUpperCase(Locale.ROOT); + if (launchMechanism.equals("VFORK") && OperatingSystem.isLinux()) { + System.err.println(""" + The VFORK launch mechanism has been removed. Please either remove the + jdk.lang.Process.launchMechanism property (preferred) or use FORK mode + instead (-Djdk.lang.Process.launchMechanism=FORK). + """); } + return LaunchMechanism.valueOf(launchMechanism); } catch (IllegalArgumentException e) { } @@ -266,7 +251,6 @@ static Process start(String[] cmdarray, *
      *   1 - fork(2) and exec(2)
      *   2 - posix_spawn(3P)
-     *   3 - vfork(2) and exec(2)
      * 
* @param fds an array of three file descriptors. * Indexes 0, 1, and 2 correspond to standard input, diff --git a/src/java.base/unix/native/libjava/ProcessImpl_md.c b/src/java.base/unix/native/libjava/ProcessImpl_md.c index 1d0c8d21d3757..401ad5bfe01f6 100644 --- a/src/java.base/unix/native/libjava/ProcessImpl_md.c +++ b/src/java.base/unix/native/libjava/ProcessImpl_md.c @@ -57,7 +57,7 @@ * changing paths... * - then exec(2) the target binary * - * There are three ways to fork off: + * On the OS-side are four ways to fork off: * * A) fork(2). Portable and safe (no side effects) but may fail with ENOMEM on * all Unices when invoked from a VM with a high memory footprint. On Unices @@ -74,34 +74,23 @@ * * B) vfork(2): Portable and fast but very unsafe. It bypasses the memory * problems related to fork(2) by starting the child in the memory image of - * the parent. Things that can go wrong include: - * - Programming errors in the child process before the exec(2) call may - * trash memory in the parent process, most commonly the stack of the - * thread invoking vfork. - * - Signals received by the child before the exec(2) call may be at best - * misdirected to the parent, at worst immediately kill child and parent. - * - * This is mitigated by very strict rules about what one is allowed to do in - * the child process between vfork(2) and exec(2), which is basically nothing. - * However, we always broke this rule by doing the pre-exec work between - * vfork(2) and exec(2). - * - * Also note that vfork(2) has been deprecated by the OpenGroup, presumably - * because of its many dangers. + * the parent. + * *** This mode is inherently dangerous, and the danger partly outside the control + * of the programmer (for details, see JDK-8357090). Therefore, we deprecated + * the vfork mode with JDK 25 and removed if with JDK 26. *** * * C) clone(2): This is a Linux specific call which gives the caller fine * grained control about how exactly the process fork is executed. It is * powerful, but Linux-specific. * - * Aside from these three possibilities there is a forth option: posix_spawn(3). - * Where fork/vfork/clone all fork off the process and leave pre-exec work and - * calling exec(2) to the user, posix_spawn(3) offers the user fork+exec-like - * functionality in one package, similar to CreateProcess() on Windows. - * - * It is not a system call in itself, but usually a wrapper implemented within - * the libc in terms of one of (fork|vfork|clone)+exec - so whether or not it - * has advantages over calling the naked (fork|vfork|clone) functions depends - * on how posix_spawn(3) is implemented. + * D) posix_spawn(3): Where fork/vfork/clone all fork off the process and leave + * pre-exec work and calling exec(2) to the user, posix_spawn(3) offers the user + * fork+exec-like functionality in one package, similar to CreateProcess() on Windows. + * It is not a system call, but usually a wrapper implemented within the libc in terms + * of one of (fork|vfork|clone)+exec - so whether or not it has advantages over calling + * the naked (fork|vfork|clone) functions depends on how posix_spawn(3) is implemented. + * Note, however, that even if posix_spawn(3) uses vfork(2) internally, that is still fine - + * the assumption here is that the libc developers know how to mitigate the vfork problems. * * Note that when using posix_spawn(3), we exec twice: first a tiny binary called * the jspawnhelper, then in the jspawnhelper we do the pre-exec work and exec a @@ -486,28 +475,6 @@ static int copystrings(char *buf, int offset, const char * const *arg) { __attribute_noinline__ #endif -/* vfork(2) is deprecated on Darwin */ -#ifndef __APPLE__ -static pid_t -vforkChild(ChildStuff *c) { - volatile pid_t resultPid; - - /* - * We separate the call to vfork into a separate function to make - * very sure to keep stack of child from corrupting stack of parent, - * as suggested by the scary gcc warning: - * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork' - */ - resultPid = vfork(); - - if (resultPid == 0) { - childProcess(c); - } - assert(resultPid != 0); /* childProcess never returns */ - return resultPid; -} -#endif - static pid_t forkChild(ChildStuff *c) { pid_t resultPid; @@ -652,11 +619,6 @@ spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) static pid_t startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) { switch (c->mode) { -/* vfork(2) is deprecated on Darwin*/ - #ifndef __APPLE__ - case MODE_VFORK: - return vforkChild(c); - #endif case MODE_FORK: return forkChild(c); case MODE_POSIX_SPAWN: @@ -765,9 +727,6 @@ Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env, if (resultPid < 0) { switch (c->mode) { - case MODE_VFORK: - throwInternalIOException(env, errno, "vfork failed", c->mode); - break; case MODE_FORK: throwInternalIOException(env, errno, "fork failed", c->mode); break; diff --git a/src/java.base/unix/native/libjava/childproc.c b/src/java.base/unix/native/libjava/childproc.c index 7a21b86565f82..9ad1bdef051e8 100644 --- a/src/java.base/unix/native/libjava/childproc.c +++ b/src/java.base/unix/native/libjava/childproc.c @@ -205,31 +205,6 @@ initVectorFromBlock(const char**vector, const char* block, int count) vector[count] = NULL; } -/** - * Exec FILE as a traditional Bourne shell script (i.e. one without #!). - * If we could do it over again, we would probably not support such an ancient - * misfeature, but compatibility wins over sanity. The original support for - * this was imported accidentally from execvp(). - */ -static void -execve_as_traditional_shell_script(const char *file, - const char *argv[], - const char *const envp[]) -{ - /* Use the extra word of space provided for us in argv by caller. */ - const char *argv0 = argv[0]; - const char *const *end = argv; - while (*end != NULL) - ++end; - memmove(argv+2, argv+1, (end-argv) * sizeof(*end)); - argv[0] = "/bin/sh"; - argv[1] = file; - execve(argv[0], (char **) argv, (char **) envp); - /* Can't even exec /bin/sh? Big trouble, but let's soldier on... */ - memmove(argv+1, argv+2, (end-argv) * sizeof(*end)); - argv[0] = argv0; -} - /** * Like execve(2), except that in case of ENOEXEC, FILE is assumed to * be a shell script and the system default shell is invoked to run it. @@ -239,16 +214,9 @@ execve_with_shell_fallback(int mode, const char *file, const char *argv[], const char *const envp[]) { - if (mode == MODE_VFORK) { - /* shared address space; be very careful. */ - execve(file, (char **) argv, (char **) envp); - if (errno == ENOEXEC) - execve_as_traditional_shell_script(file, argv, envp); - } else { - /* unshared address space; we can mutate environ. */ - environ = (char **) envp; - execvp(file, (char **) argv); - } + /* unshared address space; we can mutate environ. */ + environ = (char **) envp; + execvp(file, (char **) argv); } /** @@ -406,12 +374,10 @@ childProcess(void *arg) if (p->pdir != NULL && chdir(p->pdir) < 0) goto WhyCantJohnnyExec; - // Reset any mask signals from parent, but not in VFORK mode - if (p->mode != MODE_VFORK) { - sigset_t unblock_signals; - sigemptyset(&unblock_signals); - sigprocmask(SIG_SETMASK, &unblock_signals, NULL); - } + // Reset any mask signals from parent + sigset_t unblock_signals; + sigemptyset(&unblock_signals); + sigprocmask(SIG_SETMASK, &unblock_signals, NULL); if (fcntl(FAIL_FILENO, F_SETFD, FD_CLOEXEC) == -1) goto WhyCantJohnnyExec; diff --git a/src/java.base/unix/native/libjava/childproc.h b/src/java.base/unix/native/libjava/childproc.h index 974fac3bdddda..353cfc4941434 100644 --- a/src/java.base/unix/native/libjava/childproc.h +++ b/src/java.base/unix/native/libjava/childproc.h @@ -77,7 +77,6 @@ extern char **environ; */ #define MODE_FORK 1 #define MODE_POSIX_SPAWN 2 -#define MODE_VFORK 3 typedef struct _ChildStuff {