author | chegar |
Thu, 17 Oct 2019 20:54:25 +0100 | |
branch | datagramsocketimpl-branch |
changeset 58679 | 9c3209ff7550 |
parent 58678 | 9cf78a70fa4f |
parent 55403 | 8d50ff464ae5 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
52364
750b500ef4de
8212828: (process) Provide a way for Runtime.exec to use posix_spawn on linux
stuefe
parents:
47216
diff
changeset
|
2 |
* Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
#undef _LARGEFILE64_SOURCE |
|
27 |
#define _LARGEFILE64_SOURCE 1 |
|
28 |
||
29 |
#include "jni.h" |
|
30 |
#include "jvm.h" |
|
31 |
#include "jvm_md.h" |
|
32 |
#include "jni_util.h" |
|
33 |
#include "io_util.h" |
|
34 |
||
35 |
/* |
|
36 |
* Platform-specific support for java.lang.Process |
|
37 |
*/ |
|
38 |
#include <assert.h> |
|
39 |
#include <stddef.h> |
|
40 |
#include <stdlib.h> |
|
41 |
#include <sys/types.h> |
|
42 |
#include <ctype.h> |
|
11691
ff8aec7600fe
7133301: (process) UNIXProcess_md.c should include sys/wait.h rather than wait.h
ngmr
parents:
5506
diff
changeset
|
43 |
#include <sys/wait.h> |
2 | 44 |
#include <signal.h> |
45 |
#include <string.h> |
|
46 |
||
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
47 |
#include <spawn.h> |
12047
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
11691
diff
changeset
|
48 |
|
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
49 |
#include "childproc.h" |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
50 |
|
2948
7f4d7737d38f
6853336: (process) disable or remove clone-exec feature (6850720)
tbell
parents:
2946
diff
changeset
|
51 |
/* |
53722
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
52 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
53 |
* When starting a child on Unix, we need to do three things: |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
54 |
* - fork off |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
55 |
* - in the child process, do some pre-exec work: duping/closing file |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
56 |
* descriptors to set up stdio-redirection, setting environment variables, |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
57 |
* changing paths... |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
58 |
* - then exec(2) the target binary |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
59 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
60 |
* There are three ways to fork off: |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
61 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
62 |
* A) fork(2). Portable and safe (no side effects) but may fail with ENOMEM on |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
63 |
* all Unices when invoked from a VM with a high memory footprint. On Unices |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
64 |
* with strict no-overcommit policy this problem is most visible. |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
65 |
* |
53722
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
66 |
* This is because forking the VM will first create a child process with |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
67 |
* theoretically the same memory footprint as the parent - even if you plan |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
68 |
* to follow up with exec'ing a tiny binary. In reality techniques like |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
69 |
* copy-on-write etc mitigate the problem somewhat but we still run the risk |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
70 |
* of hitting system limits. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
71 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
72 |
* For a Linux centric description of this problem, see the documentation on |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
73 |
* /proc/sys/vm/overcommit_memory in Linux proc(5). |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
74 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
75 |
* B) vfork(2): Portable and fast but very unsafe. It bypasses the memory |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
76 |
* problems related to fork(2) by starting the child in the memory image of |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
77 |
* the parent. Things that can go wrong include: |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
78 |
* - Programming errors in the child process before the exec(2) call may |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
79 |
* trash memory in the parent process, most commonly the stack of the |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
80 |
* thread invoking vfork. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
81 |
* - Signals received by the child before the exec(2) call may be at best |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
82 |
* misdirected to the parent, at worst immediately kill child and parent. |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
83 |
* |
53722
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
84 |
* This is mitigated by very strict rules about what one is allowed to do in |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
85 |
* the child process between vfork(2) and exec(2), which is basically nothing. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
86 |
* However, we always broke this rule by doing the pre-exec work between |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
87 |
* vfork(2) and exec(2). |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
88 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
89 |
* Also note that vfork(2) has been deprecated by the OpenGroup, presumably |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
90 |
* because of its many dangers. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
91 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
92 |
* C) clone(2): This is a Linux specific call which gives the caller fine |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
93 |
* grained control about how exactly the process fork is executed. It is |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
94 |
* powerful, but Linux-specific. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
95 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
96 |
* Aside from these three possibilities there is a forth option: posix_spawn(3). |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
97 |
* Where fork/vfork/clone all fork off the process and leave pre-exec work and |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
98 |
* calling exec(2) to the user, posix_spawn(3) offers the user fork+exec-like |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
99 |
* functionality in one package, similar to CreateProcess() on Windows. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
100 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
101 |
* It is not a system call in itself, but usually a wrapper implemented within |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
102 |
* the libc in terms of one of (fork|vfork|clone)+exec - so whether or not it |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
103 |
* has advantages over calling the naked (fork|vfork|clone) functions depends |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
104 |
* on how posix_spawn(3) is implemented. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
105 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
106 |
* Note that when using posix_spawn(3), we exec twice: first a tiny binary called |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
107 |
* the jspawnhelper, then in the jspawnhelper we do the pre-exec work and exec a |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
108 |
* second time, this time the target binary (similar to the "exec-twice-technique" |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
109 |
* described in http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-September/055333.html). |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
110 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
111 |
* This is a JDK-specific implementation detail which just happens to be |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
112 |
* implemented for jdk.lang.Process.launchMechanism=POSIX_SPAWN. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
113 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
114 |
* --- Linux-specific --- |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
115 |
* |
53722
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
116 |
* How does glibc implement posix_spawn? |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
117 |
* (see: sysdeps/posix/spawni.c for glibc < 2.24, |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
118 |
* sysdeps/unix/sysv/linux/spawni.c for glibc >= 2.24): |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
119 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
120 |
* 1) Before glibc 2.4 (released 2006), posix_spawn(3) used just fork(2)/exec(2). |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
121 |
* This would be bad for the JDK since we would risk the known memory issues with |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
122 |
* fork(2). But since this only affects glibc variants which have long been |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
123 |
* phased out by modern distributions, this is irrelevant. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
124 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
125 |
* 2) Between glibc 2.4 and glibc 2.23, posix_spawn uses either fork(2) or |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
126 |
* vfork(2) depending on how exactly the user called posix_spawn(3): |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
127 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
128 |
* <quote> |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
129 |
* The child process is created using vfork(2) instead of fork(2) when |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
130 |
* either of the following is true: |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
131 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
132 |
* * the spawn-flags element of the attributes object pointed to by |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
133 |
* attrp contains the GNU-specific flag POSIX_SPAWN_USEVFORK; or |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
134 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
135 |
* * file_actions is NULL and the spawn-flags element of the attributes |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
136 |
* object pointed to by attrp does not contain |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
137 |
* POSIX_SPAWN_SETSIGMASK, POSIX_SPAWN_SETSIGDEF, |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
138 |
* POSIX_SPAWN_SETSCHEDPARAM, POSIX_SPAWN_SETSCHEDULER, |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
139 |
* POSIX_SPAWN_SETPGROUP, or POSIX_SPAWN_RESETIDS. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
140 |
* </quote> |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
141 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
142 |
* Due to the way the JDK calls posix_spawn(3), it would therefore call vfork(2). |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
143 |
* So we would avoid the fork(2) memory problems. However, there still remains the |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
144 |
* risk associated with vfork(2). But it is smaller than were we to call vfork(2) |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
145 |
* directly since we use the jspawnhelper, moving all pre-exec work off to after |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
146 |
* the first exec, thereby reducing the vulnerable time window. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
147 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
148 |
* 3) Since glibc >= 2.24, glibc uses clone+exec: |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
149 |
* |
53722
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
150 |
* new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size, |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
151 |
* CLONE_VM | CLONE_VFORK | SIGCHLD, &args); |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
152 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
153 |
* This is even better than (2): |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
154 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
155 |
* CLONE_VM means we run in the parent's memory image, as with (2) |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
156 |
* CLONE_VFORK means parent waits until we exec, as with (2) |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
157 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
158 |
* However, error possibilities are further reduced since: |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
159 |
* - posix_spawn(3) passes a separate stack for the child to run on, eliminating |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
160 |
* the danger of trashing the forking thread's stack in the parent process. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
161 |
* - posix_spawn(3) takes care to temporarily block all incoming signals to the |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
162 |
* child process until the first exec(2) has been called, |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
163 |
* |
53722
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
164 |
* TL;DR |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
165 |
* Calling posix_spawn(3) for glibc |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
166 |
* (2) < 2.24 is not perfect but still better than using plain vfork(2), since |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
167 |
* the chance of an error happening is greatly reduced |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
168 |
* (3) >= 2.24 is the best option - portable, fast and as safe as possible. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
169 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
170 |
* --- |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
171 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
172 |
* How does muslc implement posix_spawn? |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
173 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
174 |
* They always did use the clone (.. CLONE_VM | CLONE_VFORK ...) |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
175 |
* technique. So we are safe to use posix_spawn() here regardless of muslc |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
176 |
* version. |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
177 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
178 |
* </Linux-specific> |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
179 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
180 |
* |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
181 |
* Based on the above analysis, we are currently defaulting to posix_spawn() |
f037d1a2e899
8212828: (process) Change the Process launch mechanism default on Linux to be posix_spawn
stuefe
parents:
52364
diff
changeset
|
182 |
* on all Unices including Linux. |
2948
7f4d7737d38f
6853336: (process) disable or remove clone-exec feature (6850720)
tbell
parents:
2946
diff
changeset
|
183 |
*/ |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
184 |
|
2 | 185 |
static void |
186 |
setSIGCHLDHandler(JNIEnv *env) |
|
187 |
{ |
|
188 |
/* There is a subtle difference between having the signal handler |
|
189 |
* for SIGCHLD be SIG_DFL and SIG_IGN. We cannot obtain process |
|
190 |
* termination information for child processes if the signal |
|
191 |
* handler is SIG_IGN. It must be SIG_DFL. |
|
192 |
* |
|
193 |
* We used to set the SIGCHLD handler only on Linux, but it's |
|
194 |
* safest to set it unconditionally. |
|
195 |
* |
|
196 |
* Consider what happens if java's parent process sets the SIGCHLD |
|
197 |
* handler to SIG_IGN. Normally signal handlers are inherited by |
|
198 |
* children, but SIGCHLD is a controversial case. Solaris appears |
|
199 |
* to always reset it to SIG_DFL, but this behavior may be |
|
200 |
* non-standard-compliant, and we shouldn't rely on it. |
|
201 |
* |
|
202 |
* References: |
|
203 |
* http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html |
|
204 |
* http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html |
|
205 |
*/ |
|
206 |
struct sigaction sa; |
|
207 |
sa.sa_handler = SIG_DFL; |
|
208 |
sigemptyset(&sa.sa_mask); |
|
209 |
sa.sa_flags = SA_NOCLDSTOP | SA_RESTART; |
|
210 |
if (sigaction(SIGCHLD, &sa, NULL) < 0) |
|
211 |
JNU_ThrowInternalError(env, "Can't set SIGCHLD handler"); |
|
212 |
} |
|
213 |
||
214 |
static void* |
|
215 |
xmalloc(JNIEnv *env, size_t size) |
|
216 |
{ |
|
217 |
void *p = malloc(size); |
|
218 |
if (p == NULL) |
|
219 |
JNU_ThrowOutOfMemoryError(env, NULL); |
|
220 |
return p; |
|
221 |
} |
|
222 |
||
223 |
#define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type))) |
|
224 |
||
225 |
/** |
|
226 |
* If PATH is not defined, the OS provides some default value. |
|
227 |
* Unfortunately, there's no portable way to get this value. |
|
228 |
* Fortunately, it's only needed if the child has PATH while we do not. |
|
229 |
*/ |
|
230 |
static const char* |
|
231 |
defaultPath(void) |
|
232 |
{ |
|
233 |
#ifdef __solaris__ |
|
234 |
/* These really are the Solaris defaults! */ |
|
235 |
return (geteuid() == 0 || getuid() == 0) ? |
|
41107
567f832618d7
8165161: Solaris: /usr/ccs /opt/sfw and /opt/csw are dead, references should be expunged
alanbur
parents:
40745
diff
changeset
|
236 |
"/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" : |
567f832618d7
8165161: Solaris: /usr/ccs /opt/sfw and /opt/csw are dead, references should be expunged
alanbur
parents:
40745
diff
changeset
|
237 |
"/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:"; |
2 | 238 |
#else |
239 |
return ":/bin:/usr/bin"; /* glibc */ |
|
240 |
#endif |
|
241 |
} |
|
242 |
||
243 |
static const char* |
|
244 |
effectivePath(void) |
|
245 |
{ |
|
246 |
const char *s = getenv("PATH"); |
|
247 |
return (s != NULL) ? s : defaultPath(); |
|
248 |
} |
|
249 |
||
250 |
static int |
|
251 |
countOccurrences(const char *s, char c) |
|
252 |
{ |
|
253 |
int count; |
|
254 |
for (count = 0; *s != '\0'; s++) |
|
255 |
count += (*s == c); |
|
256 |
return count; |
|
257 |
} |
|
258 |
||
259 |
static const char * const * |
|
16860
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
260 |
effectivePathv(JNIEnv *env) |
2 | 261 |
{ |
16860
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
262 |
char *p; |
2 | 263 |
int i; |
16860
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
264 |
const char *path = effectivePath(); |
2 | 265 |
int count = countOccurrences(path, ':') + 1; |
16860
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
266 |
size_t pathvsize = sizeof(const char *) * (count+1); |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
267 |
size_t pathsize = strlen(path) + 1; |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
268 |
const char **pathv = (const char **) xmalloc(env, pathvsize + pathsize); |
2 | 269 |
|
16860
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
270 |
if (pathv == NULL) |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
271 |
return NULL; |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
272 |
p = (char *) pathv + pathvsize; |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
273 |
memcpy(p, path, pathsize); |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
274 |
/* split PATH by replacing ':' with NULs; empty components => "." */ |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
275 |
for (i = 0; i < count; i++) { |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
276 |
char *q = p + strcspn(p, ":"); |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
277 |
pathv[i] = (p == q) ? "." : p; |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
278 |
*q = '\0'; |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
279 |
p = q + 1; |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
280 |
} |
2 | 281 |
pathv[count] = NULL; |
16860
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
282 |
return pathv; |
2 | 283 |
} |
284 |
||
285 |
JNIEXPORT void JNICALL |
|
28665
fe8344cf6496
8071481: (Process) Merge UNIXProcess.java into ProcessImpl.java
rriggs
parents:
25991
diff
changeset
|
286 |
Java_java_lang_ProcessImpl_init(JNIEnv *env, jclass clazz) |
2 | 287 |
{ |
16860
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
288 |
parentPathv = effectivePathv(env); |
22641
e47f8892133e
8033372: Check jdk/src/share/native/java/lang for JNI pending exception issues
alanb
parents:
22597
diff
changeset
|
289 |
CHECK_NULL(parentPathv); |
2 | 290 |
setSIGCHLDHandler(env); |
291 |
} |
|
292 |
||
293 |
||
294 |
#ifndef WIFEXITED |
|
295 |
#define WIFEXITED(status) (((status)&0xFF) == 0) |
|
296 |
#endif |
|
297 |
||
298 |
#ifndef WEXITSTATUS |
|
299 |
#define WEXITSTATUS(status) (((status)>>8)&0xFF) |
|
300 |
#endif |
|
301 |
||
302 |
#ifndef WIFSIGNALED |
|
303 |
#define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0) |
|
304 |
#endif |
|
305 |
||
306 |
#ifndef WTERMSIG |
|
307 |
#define WTERMSIG(status) ((status)&0x7F) |
|
308 |
#endif |
|
309 |
||
310 |
static const char * |
|
311 |
getBytes(JNIEnv *env, jbyteArray arr) |
|
312 |
{ |
|
313 |
return arr == NULL ? NULL : |
|
314 |
(const char*) (*env)->GetByteArrayElements(env, arr, NULL); |
|
315 |
} |
|
316 |
||
317 |
static void |
|
318 |
releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr) |
|
319 |
{ |
|
320 |
if (parr != NULL) |
|
321 |
(*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT); |
|
322 |
} |
|
323 |
||
30784 | 324 |
#define IOE_FORMAT "error=%d, %s" |
325 |
||
2 | 326 |
static void |
327 |
throwIOException(JNIEnv *env, int errnum, const char *defaultDetail) |
|
328 |
{ |
|
329 |
const char *detail = defaultDetail; |
|
330 |
char *errmsg; |
|
30784 | 331 |
size_t fmtsize; |
32846
5383225ebd0d
8133249: Occasional SIGSEGV: non thread-safe use of strerr in getLastErrorString
robm
parents:
30899
diff
changeset
|
332 |
char tmpbuf[1024]; |
2 | 333 |
jstring s; |
334 |
||
335 |
if (errnum != 0) { |
|
32846
5383225ebd0d
8133249: Occasional SIGSEGV: non thread-safe use of strerr in getLastErrorString
robm
parents:
30899
diff
changeset
|
336 |
int ret = getErrorString(errnum, tmpbuf, sizeof(tmpbuf)); |
5383225ebd0d
8133249: Occasional SIGSEGV: non thread-safe use of strerr in getLastErrorString
robm
parents:
30899
diff
changeset
|
337 |
if (ret != EINVAL) |
5383225ebd0d
8133249: Occasional SIGSEGV: non thread-safe use of strerr in getLastErrorString
robm
parents:
30899
diff
changeset
|
338 |
detail = tmpbuf; |
2 | 339 |
} |
340 |
/* ASCII Decimal representation uses 2.4 times as many bits as binary. */ |
|
30784 | 341 |
fmtsize = sizeof(IOE_FORMAT) + strlen(detail) + 3 * sizeof(errnum); |
342 |
errmsg = NEW(char, fmtsize); |
|
16860
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
343 |
if (errmsg == NULL) |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
344 |
return; |
8fecebee12b0
8008118: (process) Possible null pointer dereference in jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jzavgren
parents:
13149
diff
changeset
|
345 |
|
30784 | 346 |
snprintf(errmsg, fmtsize, IOE_FORMAT, errnum, detail); |
2 | 347 |
s = JNU_NewStringPlatform(env, errmsg); |
348 |
if (s != NULL) { |
|
349 |
jobject x = JNU_NewObjectByName(env, "java/io/IOException", |
|
350 |
"(Ljava/lang/String;)V", s); |
|
351 |
if (x != NULL) |
|
352 |
(*env)->Throw(env, x); |
|
353 |
} |
|
354 |
free(errmsg); |
|
355 |
} |
|
356 |
||
55403
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
357 |
/** |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
358 |
* Throws an IOException with a message composed from the result of waitpid status. |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
359 |
*/ |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
360 |
static void throwExitCause(JNIEnv *env, int pid, int status) { |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
361 |
char ebuf[128]; |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
362 |
if (WIFEXITED(status)) { |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
363 |
snprintf(ebuf, sizeof ebuf, |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
364 |
"Failed to exec spawn helper: pid: %d, exit value: %d", |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
365 |
pid, WEXITSTATUS(status)); |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
366 |
} else if (WIFSIGNALED(status)) { |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
367 |
snprintf(ebuf, sizeof ebuf, |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
368 |
"Failed to exec spawn helper: pid: %d, signal: %d", |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
369 |
pid, WTERMSIG(status)); |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
370 |
} else { |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
371 |
snprintf(ebuf, sizeof ebuf, |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
372 |
"Failed to exec spawn helper: pid: %d, status: 0x%08x", |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
373 |
pid, status); |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
374 |
} |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
375 |
throwIOException(env, 0, ebuf); |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
376 |
} |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
377 |
|
2 | 378 |
#ifdef DEBUG_PROCESS |
379 |
/* Debugging process code is difficult; where to write debug output? */ |
|
380 |
static void |
|
381 |
debugPrint(char *format, ...) |
|
382 |
{ |
|
383 |
FILE *tty = fopen("/dev/tty", "w"); |
|
384 |
va_list ap; |
|
385 |
va_start(ap, format); |
|
386 |
vfprintf(tty, format, ap); |
|
387 |
va_end(ap); |
|
388 |
fclose(tty); |
|
389 |
} |
|
390 |
#endif /* DEBUG_PROCESS */ |
|
391 |
||
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
392 |
static void |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
393 |
copyPipe(int from[2], int to[2]) |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
394 |
{ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
395 |
to[0] = from[0]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
396 |
to[1] = from[1]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
397 |
} |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
398 |
|
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
399 |
/* arg is an array of pointers to 0 terminated strings. array is terminated |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
400 |
* by a null element. |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
401 |
* |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
402 |
* *nelems and *nbytes receive the number of elements of array (incl 0) |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
403 |
* and total number of bytes (incl. 0) |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
404 |
* Note. An empty array will have one null element |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
405 |
* But if arg is null, then *nelems set to 0, and *nbytes to 0 |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
406 |
*/ |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
407 |
static void arraysize(const char * const *arg, int *nelems, int *nbytes) |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
408 |
{ |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
409 |
int i, bytes, count; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
410 |
const char * const *a = arg; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
411 |
char *p; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
412 |
int *q; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
413 |
if (arg == 0) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
414 |
*nelems = 0; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
415 |
*nbytes = 0; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
416 |
return; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
417 |
} |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
418 |
/* count the array elements and number of bytes */ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
419 |
for (count=0, bytes=0; *a != 0; count++, a++) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
420 |
bytes += strlen(*a)+1; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
421 |
} |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
422 |
*nbytes = bytes; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
423 |
*nelems = count+1; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
424 |
} |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
425 |
|
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
426 |
/* copy the strings from arg[] into buf, starting at given offset |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
427 |
* return new offset to next free byte |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
428 |
*/ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
429 |
static int copystrings(char *buf, int offset, const char * const *arg) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
430 |
char *p; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
431 |
const char * const *a; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
432 |
int count=0; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
433 |
|
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
434 |
if (arg == 0) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
435 |
return offset; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
436 |
} |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
437 |
for (p=buf+offset, a=arg; *a != 0; a++) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
438 |
int len = strlen(*a) +1; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
439 |
memcpy(p, *a, len); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
440 |
p += len; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
441 |
count += len; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
442 |
} |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
443 |
return offset+count; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
444 |
} |
2 | 445 |
|
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
446 |
/** |
29724
638809ff54f3
7021006: (process) Remove disabled clone-exec feature
rriggs
parents:
28665
diff
changeset
|
447 |
* We are unusually paranoid; use of vfork is |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
448 |
* especially likely to tickle gcc/glibc bugs. |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
449 |
*/ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
450 |
#ifdef __attribute_noinline__ /* See: sys/cdefs.h */ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
451 |
__attribute_noinline__ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
452 |
#endif |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
453 |
|
40745
6d7a656b1612
8161360: Deprecated vfork() should not be used on Solaris
alanbur
parents:
32846
diff
changeset
|
454 |
/* vfork(2) is deprecated on Solaris */ |
6d7a656b1612
8161360: Deprecated vfork() should not be used on Solaris
alanbur
parents:
32846
diff
changeset
|
455 |
#ifndef __solaris__ |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
456 |
static pid_t |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
457 |
vforkChild(ChildStuff *c) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
458 |
volatile pid_t resultPid; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
459 |
|
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
460 |
/* |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
461 |
* We separate the call to vfork into a separate function to make |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
462 |
* very sure to keep stack of child from corrupting stack of parent, |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
463 |
* as suggested by the scary gcc warning: |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
464 |
* warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork' |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
465 |
*/ |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
466 |
resultPid = vfork(); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
467 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
468 |
if (resultPid == 0) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
469 |
childProcess(c); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
470 |
} |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
471 |
assert(resultPid != 0); /* childProcess never returns */ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
472 |
return resultPid; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
473 |
} |
40745
6d7a656b1612
8161360: Deprecated vfork() should not be used on Solaris
alanbur
parents:
32846
diff
changeset
|
474 |
#endif |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
475 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
476 |
static pid_t |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
477 |
forkChild(ChildStuff *c) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
478 |
pid_t resultPid; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
479 |
|
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
480 |
/* |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
481 |
* From Solaris fork(2): In Solaris 10, a call to fork() is |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
482 |
* identical to a call to fork1(); only the calling thread is |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
483 |
* replicated in the child process. This is the POSIX-specified |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
484 |
* behavior for fork(). |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
485 |
*/ |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
486 |
resultPid = fork(); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
487 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
488 |
if (resultPid == 0) { |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
489 |
childProcess(c); |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
490 |
} |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
491 |
assert(resultPid != 0); /* childProcess never returns */ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
492 |
return resultPid; |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
493 |
} |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
494 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
495 |
static pid_t |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
496 |
spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
497 |
pid_t resultPid; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
498 |
jboolean isCopy; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
499 |
int i, offset, rval, bufsize, magic; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
500 |
char *buf, buf1[16]; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
501 |
char *hlpargs[2]; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
502 |
SpawnInfo sp; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
503 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
504 |
/* need to tell helper which fd is for receiving the childstuff |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
505 |
* and which fd to send response back on |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
506 |
*/ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
507 |
snprintf(buf1, sizeof(buf1), "%d:%d", c->childenv[0], c->fail[1]); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
508 |
/* put the fd string as argument to the helper cmd */ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
509 |
hlpargs[0] = buf1; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
510 |
hlpargs[1] = 0; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
511 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
512 |
/* Following items are sent down the pipe to the helper |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
513 |
* after it is spawned. |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
514 |
* All strings are null terminated. All arrays of strings |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
515 |
* have an empty string for termination. |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
516 |
* - the ChildStuff struct |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
517 |
* - the SpawnInfo struct |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
518 |
* - the argv strings array |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
519 |
* - the envv strings array |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
520 |
* - the home directory string |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
521 |
* - the parentPath string |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
522 |
* - the parentPathv array |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
523 |
*/ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
524 |
/* First calculate the sizes */ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
525 |
arraysize(c->argv, &sp.nargv, &sp.argvBytes); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
526 |
bufsize = sp.argvBytes; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
527 |
arraysize(c->envv, &sp.nenvv, &sp.envvBytes); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
528 |
bufsize += sp.envvBytes; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
529 |
sp.dirlen = c->pdir == 0 ? 0 : strlen(c->pdir)+1; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
530 |
bufsize += sp.dirlen; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
531 |
arraysize(parentPathv, &sp.nparentPathv, &sp.parentPathvBytes); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
532 |
bufsize += sp.parentPathvBytes; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
533 |
/* We need to clear FD_CLOEXEC if set in the fds[]. |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
534 |
* Files are created FD_CLOEXEC in Java. |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
535 |
* Otherwise, they will be closed when the target gets exec'd */ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
536 |
for (i=0; i<3; i++) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
537 |
if (c->fds[i] != -1) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
538 |
int flags = fcntl(c->fds[i], F_GETFD); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
539 |
if (flags & FD_CLOEXEC) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
540 |
fcntl(c->fds[i], F_SETFD, flags & (~1)); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
541 |
} |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
542 |
} |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
543 |
} |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
544 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
545 |
rval = posix_spawn(&resultPid, helperpath, 0, 0, (char * const *) hlpargs, environ); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
546 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
547 |
if (rval != 0) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
548 |
return -1; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
549 |
} |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
550 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
551 |
/* now the lengths are known, copy the data */ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
552 |
buf = NEW(char, bufsize); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
553 |
if (buf == 0) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
554 |
return -1; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
555 |
} |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
556 |
offset = copystrings(buf, 0, &c->argv[0]); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
557 |
offset = copystrings(buf, offset, &c->envv[0]); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
558 |
memcpy(buf+offset, c->pdir, sp.dirlen); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
559 |
offset += sp.dirlen; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
560 |
offset = copystrings(buf, offset, parentPathv); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
561 |
assert(offset == bufsize); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
562 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
563 |
magic = magicNumber(); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
564 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
565 |
/* write the two structs and the data buffer */ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
566 |
write(c->childenv[1], (char *)&magic, sizeof(magic)); // magic number first |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
567 |
write(c->childenv[1], (char *)c, sizeof(*c)); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
568 |
write(c->childenv[1], (char *)&sp, sizeof(sp)); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
569 |
write(c->childenv[1], buf, bufsize); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
570 |
free(buf); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
571 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
572 |
/* In this mode an external main() in invoked which calls back into |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
573 |
* childProcess() in this file, rather than directly |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
574 |
* via the statement below */ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
575 |
return resultPid; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
576 |
} |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
577 |
|
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
578 |
/* |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
579 |
* Start a child process running function childProcess. |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
580 |
* This function only returns in the parent. |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
581 |
*/ |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
582 |
static pid_t |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
583 |
startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
584 |
switch (c->mode) { |
40745
6d7a656b1612
8161360: Deprecated vfork() should not be used on Solaris
alanbur
parents:
32846
diff
changeset
|
585 |
/* vfork(2) is deprecated on Solaris */ |
6d7a656b1612
8161360: Deprecated vfork() should not be used on Solaris
alanbur
parents:
32846
diff
changeset
|
586 |
#ifndef __solaris__ |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
587 |
case MODE_VFORK: |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
588 |
return vforkChild(c); |
40745
6d7a656b1612
8161360: Deprecated vfork() should not be used on Solaris
alanbur
parents:
32846
diff
changeset
|
589 |
#endif |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
590 |
case MODE_FORK: |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
591 |
return forkChild(c); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
592 |
case MODE_POSIX_SPAWN: |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
593 |
return spawnChild(env, process, c, helperpath); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
594 |
default: |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
595 |
return -1; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
596 |
} |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
597 |
} |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
598 |
|
2 | 599 |
JNIEXPORT jint JNICALL |
28665
fe8344cf6496
8071481: (Process) Merge UNIXProcess.java into ProcessImpl.java
rriggs
parents:
25991
diff
changeset
|
600 |
Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env, |
2 | 601 |
jobject process, |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
602 |
jint mode, |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
603 |
jbyteArray helperpath, |
2 | 604 |
jbyteArray prog, |
605 |
jbyteArray argBlock, jint argc, |
|
606 |
jbyteArray envBlock, jint envc, |
|
607 |
jbyteArray dir, |
|
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
608 |
jintArray std_fds, |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
609 |
jboolean redirectErrorStream) |
2 | 610 |
{ |
611 |
int errnum; |
|
612 |
int resultPid = -1; |
|
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
613 |
int in[2], out[2], err[2], fail[2], childenv[2]; |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
614 |
jint *fds = NULL; |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
615 |
const char *phelperpath = NULL; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
616 |
const char *pprog = NULL; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
617 |
const char *pargBlock = NULL; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
618 |
const char *penvBlock = NULL; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
619 |
ChildStuff *c; |
2 | 620 |
|
621 |
in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1; |
|
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
622 |
childenv[0] = childenv[1] = -1; |
2 | 623 |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
624 |
if ((c = NEW(ChildStuff, 1)) == NULL) return -1; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
625 |
c->argv = NULL; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
626 |
c->envv = NULL; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
627 |
c->pdir = NULL; |
2 | 628 |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
629 |
/* Convert prog + argBlock into a char ** argv. |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
630 |
* Add one word room for expansion of argv for use by |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
631 |
* execve_as_traditional_shell_script. |
29724
638809ff54f3
7021006: (process) Remove disabled clone-exec feature
rriggs
parents:
28665
diff
changeset
|
632 |
* This word is also used when using posix_spawn mode |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
633 |
*/ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
634 |
assert(prog != NULL && argBlock != NULL); |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
635 |
if ((phelperpath = getBytes(env, helperpath)) == NULL) goto Catch; |
25980
76e7de7a6ef7
8054841: (process) ProcessBuilder leaks native memory
igerasim
parents:
22641
diff
changeset
|
636 |
if ((pprog = getBytes(env, prog)) == NULL) goto Catch; |
76e7de7a6ef7
8054841: (process) ProcessBuilder leaks native memory
igerasim
parents:
22641
diff
changeset
|
637 |
if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch; |
76e7de7a6ef7
8054841: (process) ProcessBuilder leaks native memory
igerasim
parents:
22641
diff
changeset
|
638 |
if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
639 |
c->argv[0] = pprog; |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
640 |
c->argc = argc + 2; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
641 |
initVectorFromBlock(c->argv+1, pargBlock, argc); |
2 | 642 |
|
643 |
if (envBlock != NULL) { |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
644 |
/* Convert envBlock into a char ** envv */ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
645 |
if ((penvBlock = getBytes(env, envBlock)) == NULL) goto Catch; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
646 |
if ((c->envv = NEW(const char *, envc + 1)) == NULL) goto Catch; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
647 |
initVectorFromBlock(c->envv, penvBlock, envc); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
648 |
} |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
649 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
650 |
if (dir != NULL) { |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
651 |
if ((c->pdir = getBytes(env, dir)) == NULL) goto Catch; |
2 | 652 |
} |
653 |
||
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
654 |
assert(std_fds != NULL); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
655 |
fds = (*env)->GetIntArrayElements(env, std_fds, NULL); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
656 |
if (fds == NULL) goto Catch; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
657 |
|
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
658 |
if ((fds[0] == -1 && pipe(in) < 0) || |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
659 |
(fds[1] == -1 && pipe(out) < 0) || |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
660 |
(fds[2] == -1 && pipe(err) < 0) || |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
661 |
(pipe(childenv) < 0) || |
2 | 662 |
(pipe(fail) < 0)) { |
663 |
throwIOException(env, errno, "Bad file descriptor"); |
|
664 |
goto Catch; |
|
665 |
} |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
666 |
c->fds[0] = fds[0]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
667 |
c->fds[1] = fds[1]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
668 |
c->fds[2] = fds[2]; |
2 | 669 |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
670 |
copyPipe(in, c->in); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
671 |
copyPipe(out, c->out); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
672 |
copyPipe(err, c->err); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
673 |
copyPipe(fail, c->fail); |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
674 |
copyPipe(childenv, c->childenv); |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
675 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
676 |
c->redirectErrorStream = redirectErrorStream; |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
677 |
c->mode = mode; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
678 |
|
55240
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
679 |
/* In posix_spawn mode, require the child process to signal aliveness |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
680 |
* right after it comes up. This is because there are implementations of |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
681 |
* posix_spawn() which do not report failed exec()s back to the caller |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
682 |
* (e.g. glibc, see JDK-8223777). In those cases, the fork() will have |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
683 |
* worked and successfully started the child process, but the exec() will |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
684 |
* have failed. There is no way for us to distinguish this from a target |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
685 |
* binary just exiting right after start. |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
686 |
* |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
687 |
* Note that we could do this additional handshake in all modes but for |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
688 |
* prudence only do it when it is needed (in posix_spawn mode). */ |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
689 |
c->sendAlivePing = (mode == MODE_POSIX_SPAWN) ? 1 : 0; |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
690 |
|
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
691 |
resultPid = startChild(env, process, c, phelperpath); |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
692 |
assert(resultPid != 0); |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
693 |
|
2 | 694 |
if (resultPid < 0) { |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
695 |
switch (c->mode) { |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
696 |
case MODE_VFORK: |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
697 |
throwIOException(env, errno, "vfork failed"); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
698 |
break; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
699 |
case MODE_FORK: |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
700 |
throwIOException(env, errno, "fork failed"); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
701 |
break; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
702 |
case MODE_POSIX_SPAWN: |
29724
638809ff54f3
7021006: (process) Remove disabled clone-exec feature
rriggs
parents:
28665
diff
changeset
|
703 |
throwIOException(env, errno, "posix_spawn failed"); |
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
704 |
break; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
705 |
} |
2 | 706 |
goto Catch; |
707 |
} |
|
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
708 |
close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec (childproc.c) */ |
50
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
709 |
|
55240
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
710 |
/* If we expect the child to ping aliveness, wait for it. */ |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
711 |
if (c->sendAlivePing) { |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
712 |
switch(readFully(fail[0], &errnum, sizeof(errnum))) { |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
713 |
case 0: /* First exec failed; */ |
55403
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
714 |
{ |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
715 |
int tmpStatus = 0; |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
716 |
int p = waitpid(resultPid, &tmpStatus, 0); |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
717 |
throwExitCause(env, p, tmpStatus); |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
718 |
goto Catch; |
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
719 |
} |
55240
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
720 |
case sizeof(errnum): |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
721 |
assert(errnum == CHILD_IS_ALIVE); |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
722 |
if (errnum != CHILD_IS_ALIVE) { |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
723 |
/* Should never happen since the first thing the spawn |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
724 |
* helper should do is to send an alive ping to the parent, |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
725 |
* before doing any subsequent work. */ |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
726 |
throwIOException(env, 0, "Bad code from spawn helper " |
55403
8d50ff464ae5
8226242: Diagnostic output for posix_spawn failure
rriggs
parents:
55240
diff
changeset
|
727 |
"(Failed to exec spawn helper)"); |
55240
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
728 |
goto Catch; |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
729 |
} |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
730 |
break; |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
731 |
default: |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
732 |
throwIOException(env, errno, "Read failed"); |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
733 |
goto Catch; |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
734 |
} |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
735 |
} |
57b93b113ec0
8223777: In posix_spawn mode, failing to exec() jspawnhelper does not result in an error
stuefe
parents:
53722
diff
changeset
|
736 |
|
50
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
737 |
switch (readFully(fail[0], &errnum, sizeof(errnum))) { |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
738 |
case 0: break; /* Exec succeeded */ |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
739 |
case sizeof(errnum): |
2 | 740 |
waitpid(resultPid, NULL, 0); |
741 |
throwIOException(env, errnum, "Exec failed"); |
|
742 |
goto Catch; |
|
50
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
743 |
default: |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
744 |
throwIOException(env, errno, "Read failed"); |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
745 |
goto Catch; |
2 | 746 |
} |
747 |
||
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
748 |
fds[0] = (in [1] != -1) ? in [1] : -1; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
749 |
fds[1] = (out[0] != -1) ? out[0] : -1; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
750 |
fds[2] = (err[0] != -1) ? err[0] : -1; |
2 | 751 |
|
752 |
Finally: |
|
753 |
/* Always clean up the child's side of the pipes */ |
|
754 |
closeSafely(in [0]); |
|
755 |
closeSafely(out[1]); |
|
756 |
closeSafely(err[1]); |
|
757 |
||
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
758 |
/* Always clean up fail and childEnv descriptors */ |
2 | 759 |
closeSafely(fail[0]); |
760 |
closeSafely(fail[1]); |
|
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
761 |
closeSafely(childenv[0]); |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
762 |
closeSafely(childenv[1]); |
2 | 763 |
|
25980
76e7de7a6ef7
8054841: (process) ProcessBuilder leaks native memory
igerasim
parents:
22641
diff
changeset
|
764 |
releaseBytes(env, helperpath, phelperpath); |
76e7de7a6ef7
8054841: (process) ProcessBuilder leaks native memory
igerasim
parents:
22641
diff
changeset
|
765 |
releaseBytes(env, prog, pprog); |
76e7de7a6ef7
8054841: (process) ProcessBuilder leaks native memory
igerasim
parents:
22641
diff
changeset
|
766 |
releaseBytes(env, argBlock, pargBlock); |
76e7de7a6ef7
8054841: (process) ProcessBuilder leaks native memory
igerasim
parents:
22641
diff
changeset
|
767 |
releaseBytes(env, envBlock, penvBlock); |
76e7de7a6ef7
8054841: (process) ProcessBuilder leaks native memory
igerasim
parents:
22641
diff
changeset
|
768 |
releaseBytes(env, dir, c->pdir); |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
769 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
770 |
free(c->argv); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
771 |
free(c->envv); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
772 |
free(c); |
2 | 773 |
|
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
774 |
if (fds != NULL) |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
775 |
(*env)->ReleaseIntArrayElements(env, std_fds, fds, 0); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
776 |
|
2 | 777 |
return resultPid; |
778 |
||
779 |
Catch: |
|
780 |
/* Clean up the parent's side of the pipes in case of failure only */ |
|
19399
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
781 |
closeSafely(in [1]); in[1] = -1; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
782 |
closeSafely(out[0]); out[0] = -1; |
e2e5122cd62e
5049299: (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion
robm
parents:
16860
diff
changeset
|
783 |
closeSafely(err[0]); err[0] = -1; |
2 | 784 |
goto Finally; |
785 |
} |
|
786 |