author | ngmr |
Tue, 31 Jan 2012 10:31:19 +0000 | |
changeset 11691 | ff8aec7600fe |
parent 5506 | 202f599c92aa |
child 12047 | 320a714614e9 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
5506 | 2 |
* Copyright (c) 1995, 2008, 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 |
#include <errno.h> |
|
47 |
#include <dirent.h> |
|
48 |
#include <unistd.h> |
|
49 |
#include <fcntl.h> |
|
50 |
#include <limits.h> |
|
51 |
||
2948
7f4d7737d38f
6853336: (process) disable or remove clone-exec feature (6850720)
tbell
parents:
2946
diff
changeset
|
52 |
/* |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
53 |
* There are 3 possible strategies we might use to "fork": |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
54 |
* |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
55 |
* - fork(2). Very portable and reliable but subject to |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
56 |
* failure due to overcommit (see the documentation on |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
57 |
* /proc/sys/vm/overcommit_memory in Linux proc(5)). |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
58 |
* This is the ancient problem of spurious failure whenever a large |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
59 |
* process starts a small subprocess. |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
60 |
* |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
61 |
* - vfork(). Using this is scary because all relevant man pages |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
62 |
* contain dire warnings, e.g. Linux vfork(2). But at least it's |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
63 |
* documented in the glibc docs and is standardized by XPG4. |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
64 |
* http://www.opengroup.org/onlinepubs/000095399/functions/vfork.html |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
65 |
* On Linux, one might think that vfork() would be implemented using |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
66 |
* the clone system call with flag CLONE_VFORK, but in fact vfork is |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
67 |
* a separate system call (which is a good sign, suggesting that |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
68 |
* vfork will continue to be supported at least on Linux). |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
69 |
* Another good sign is that glibc implements posix_spawn using |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
70 |
* vfork whenever possible. Note that we cannot use posix_spawn |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
71 |
* ourselves because there's no reliable way to close all inherited |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
72 |
* file descriptors. |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
73 |
* |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
74 |
* - clone() with flags CLONE_VM but not CLONE_THREAD. clone() is |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
75 |
* Linux-specific, but this ought to work - at least the glibc |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
76 |
* sources contain code to handle different combinations of CLONE_VM |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
77 |
* and CLONE_THREAD. However, when this was implemented, it |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
78 |
* appeared to fail on 32-bit i386 (but not 64-bit x86_64) Linux with |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
79 |
* the simple program |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
80 |
* Runtime.getRuntime().exec("/bin/true").waitFor(); |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
81 |
* with: |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
82 |
* # Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536 |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
83 |
* # Error: pthread_getattr_np failed with errno = 3 (ESRCH) |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
84 |
* We believe this is a glibc bug, reported here: |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
85 |
* http://sources.redhat.com/bugzilla/show_bug.cgi?id=10311 |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
86 |
* but the glibc maintainers closed it as WONTFIX. |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
87 |
* |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
88 |
* Based on the above analysis, we are currently using vfork() on |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
89 |
* Linux and fork() on other Unix systems, but the code to use clone() |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
90 |
* remains. |
2948
7f4d7737d38f
6853336: (process) disable or remove clone-exec feature (6850720)
tbell
parents:
2946
diff
changeset
|
91 |
*/ |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
92 |
|
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
93 |
#define START_CHILD_USE_CLONE 0 /* clone() currently disabled; see above. */ |
2948
7f4d7737d38f
6853336: (process) disable or remove clone-exec feature (6850720)
tbell
parents:
2946
diff
changeset
|
94 |
|
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
95 |
#ifndef START_CHILD_USE_CLONE |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
96 |
#ifdef __linux__ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
97 |
#define START_CHILD_USE_CLONE 1 |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
98 |
#else |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
99 |
#define START_CHILD_USE_CLONE 0 |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
100 |
#endif |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
101 |
#endif |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
102 |
|
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
103 |
/* By default, use vfork() on Linux. */ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
104 |
#ifndef START_CHILD_USE_VFORK |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
105 |
#ifdef __linux__ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
106 |
#define START_CHILD_USE_VFORK 1 |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
107 |
#else |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
108 |
#define START_CHILD_USE_VFORK 0 |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
109 |
#endif |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
110 |
#endif |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
111 |
|
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
112 |
#if START_CHILD_USE_CLONE |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
113 |
#include <sched.h> |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
114 |
#define START_CHILD_SYSTEM_CALL "clone" |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
115 |
#elif START_CHILD_USE_VFORK |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
116 |
#define START_CHILD_SYSTEM_CALL "vfork" |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
117 |
#else |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
118 |
#define START_CHILD_SYSTEM_CALL "fork" |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
119 |
#endif |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
120 |
|
2 | 121 |
#ifndef STDIN_FILENO |
122 |
#define STDIN_FILENO 0 |
|
123 |
#endif |
|
124 |
||
125 |
#ifndef STDOUT_FILENO |
|
126 |
#define STDOUT_FILENO 1 |
|
127 |
#endif |
|
128 |
||
129 |
#ifndef STDERR_FILENO |
|
130 |
#define STDERR_FILENO 2 |
|
131 |
#endif |
|
132 |
||
133 |
#ifndef SA_NOCLDSTOP |
|
134 |
#define SA_NOCLDSTOP 0 |
|
135 |
#endif |
|
136 |
||
137 |
#ifndef SA_RESTART |
|
138 |
#define SA_RESTART 0 |
|
139 |
#endif |
|
140 |
||
141 |
#define FAIL_FILENO (STDERR_FILENO + 1) |
|
142 |
||
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
143 |
/* TODO: Refactor. */ |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
144 |
#define RESTARTABLE(_cmd, _result) do { \ |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
145 |
do { \ |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
146 |
_result = _cmd; \ |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
147 |
} while((_result == -1) && (errno == EINTR)); \ |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
148 |
} while(0) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
149 |
|
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
150 |
/* This is one of the rare times it's more portable to declare an |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
151 |
* external symbol explicitly, rather than via a system header. |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
152 |
* The declaration is standardized as part of UNIX98, but there is |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
153 |
* no standard (not even de-facto) header file where the |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
154 |
* declaration is to be found. See: |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
155 |
* http://www.opengroup.org/onlinepubs/009695399/functions/environ.html |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
156 |
* http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
157 |
* |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
158 |
* "All identifiers in this volume of IEEE Std 1003.1-2001, except |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
159 |
* environ, are defined in at least one of the headers" (!) |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
160 |
*/ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
161 |
extern char **environ; |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
162 |
|
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
163 |
|
2 | 164 |
static void |
165 |
setSIGCHLDHandler(JNIEnv *env) |
|
166 |
{ |
|
167 |
/* There is a subtle difference between having the signal handler |
|
168 |
* for SIGCHLD be SIG_DFL and SIG_IGN. We cannot obtain process |
|
169 |
* termination information for child processes if the signal |
|
170 |
* handler is SIG_IGN. It must be SIG_DFL. |
|
171 |
* |
|
172 |
* We used to set the SIGCHLD handler only on Linux, but it's |
|
173 |
* safest to set it unconditionally. |
|
174 |
* |
|
175 |
* Consider what happens if java's parent process sets the SIGCHLD |
|
176 |
* handler to SIG_IGN. Normally signal handlers are inherited by |
|
177 |
* children, but SIGCHLD is a controversial case. Solaris appears |
|
178 |
* to always reset it to SIG_DFL, but this behavior may be |
|
179 |
* non-standard-compliant, and we shouldn't rely on it. |
|
180 |
* |
|
181 |
* References: |
|
182 |
* http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html |
|
183 |
* http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html |
|
184 |
*/ |
|
185 |
struct sigaction sa; |
|
186 |
sa.sa_handler = SIG_DFL; |
|
187 |
sigemptyset(&sa.sa_mask); |
|
188 |
sa.sa_flags = SA_NOCLDSTOP | SA_RESTART; |
|
189 |
if (sigaction(SIGCHLD, &sa, NULL) < 0) |
|
190 |
JNU_ThrowInternalError(env, "Can't set SIGCHLD handler"); |
|
191 |
} |
|
192 |
||
193 |
static void* |
|
194 |
xmalloc(JNIEnv *env, size_t size) |
|
195 |
{ |
|
196 |
void *p = malloc(size); |
|
197 |
if (p == NULL) |
|
198 |
JNU_ThrowOutOfMemoryError(env, NULL); |
|
199 |
return p; |
|
200 |
} |
|
201 |
||
202 |
#define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type))) |
|
203 |
||
204 |
/** |
|
205 |
* If PATH is not defined, the OS provides some default value. |
|
206 |
* Unfortunately, there's no portable way to get this value. |
|
207 |
* Fortunately, it's only needed if the child has PATH while we do not. |
|
208 |
*/ |
|
209 |
static const char* |
|
210 |
defaultPath(void) |
|
211 |
{ |
|
212 |
#ifdef __solaris__ |
|
213 |
/* These really are the Solaris defaults! */ |
|
214 |
return (geteuid() == 0 || getuid() == 0) ? |
|
215 |
"/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" : |
|
216 |
"/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:"; |
|
217 |
#else |
|
218 |
return ":/bin:/usr/bin"; /* glibc */ |
|
219 |
#endif |
|
220 |
} |
|
221 |
||
222 |
static const char* |
|
223 |
effectivePath(void) |
|
224 |
{ |
|
225 |
const char *s = getenv("PATH"); |
|
226 |
return (s != NULL) ? s : defaultPath(); |
|
227 |
} |
|
228 |
||
229 |
static int |
|
230 |
countOccurrences(const char *s, char c) |
|
231 |
{ |
|
232 |
int count; |
|
233 |
for (count = 0; *s != '\0'; s++) |
|
234 |
count += (*s == c); |
|
235 |
return count; |
|
236 |
} |
|
237 |
||
238 |
static const char * const * |
|
239 |
splitPath(JNIEnv *env, const char *path) |
|
240 |
{ |
|
241 |
const char *p, *q; |
|
242 |
char **pathv; |
|
243 |
int i; |
|
244 |
int count = countOccurrences(path, ':') + 1; |
|
245 |
||
246 |
pathv = NEW(char*, count+1); |
|
247 |
pathv[count] = NULL; |
|
248 |
for (p = path, i = 0; i < count; i++, p = q + 1) { |
|
249 |
for (q = p; (*q != ':') && (*q != '\0'); q++) |
|
250 |
; |
|
251 |
if (q == p) /* empty PATH component => "." */ |
|
252 |
pathv[i] = "./"; |
|
253 |
else { |
|
254 |
int addSlash = ((*(q - 1)) != '/'); |
|
255 |
pathv[i] = NEW(char, q - p + addSlash + 1); |
|
256 |
memcpy(pathv[i], p, q - p); |
|
257 |
if (addSlash) |
|
258 |
pathv[i][q - p] = '/'; |
|
259 |
pathv[i][q - p + addSlash] = '\0'; |
|
260 |
} |
|
261 |
} |
|
262 |
return (const char * const *) pathv; |
|
263 |
} |
|
264 |
||
265 |
/** |
|
266 |
* Cached value of JVM's effective PATH. |
|
267 |
* (We don't support putenv("PATH=...") in native code) |
|
268 |
*/ |
|
269 |
static const char *parentPath; |
|
270 |
||
271 |
/** |
|
272 |
* Split, canonicalized version of parentPath |
|
273 |
*/ |
|
274 |
static const char * const *parentPathv; |
|
275 |
||
276 |
static jfieldID field_exitcode; |
|
277 |
||
278 |
JNIEXPORT void JNICALL |
|
279 |
Java_java_lang_UNIXProcess_initIDs(JNIEnv *env, jclass clazz) |
|
280 |
{ |
|
281 |
field_exitcode = (*env)->GetFieldID(env, clazz, "exitcode", "I"); |
|
282 |
||
283 |
parentPath = effectivePath(); |
|
284 |
parentPathv = splitPath(env, parentPath); |
|
285 |
||
286 |
setSIGCHLDHandler(env); |
|
287 |
} |
|
288 |
||
289 |
||
290 |
#ifndef WIFEXITED |
|
291 |
#define WIFEXITED(status) (((status)&0xFF) == 0) |
|
292 |
#endif |
|
293 |
||
294 |
#ifndef WEXITSTATUS |
|
295 |
#define WEXITSTATUS(status) (((status)>>8)&0xFF) |
|
296 |
#endif |
|
297 |
||
298 |
#ifndef WIFSIGNALED |
|
299 |
#define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0) |
|
300 |
#endif |
|
301 |
||
302 |
#ifndef WTERMSIG |
|
303 |
#define WTERMSIG(status) ((status)&0x7F) |
|
304 |
#endif |
|
305 |
||
306 |
/* Block until a child process exits and return its exit code. |
|
307 |
Note, can only be called once for any given pid. */ |
|
308 |
JNIEXPORT jint JNICALL |
|
309 |
Java_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* env, |
|
310 |
jobject junk, |
|
311 |
jint pid) |
|
312 |
{ |
|
313 |
/* We used to use waitid() on Solaris, waitpid() on Linux, but |
|
314 |
* waitpid() is more standard, so use it on all POSIX platforms. */ |
|
315 |
int status; |
|
316 |
/* Wait for the child process to exit. This returns immediately if |
|
317 |
the child has already exited. */ |
|
318 |
while (waitpid(pid, &status, 0) < 0) { |
|
319 |
switch (errno) { |
|
320 |
case ECHILD: return 0; |
|
321 |
case EINTR: break; |
|
322 |
default: return -1; |
|
323 |
} |
|
324 |
} |
|
325 |
||
326 |
if (WIFEXITED(status)) { |
|
327 |
/* |
|
328 |
* The child exited normally; get its exit code. |
|
329 |
*/ |
|
330 |
return WEXITSTATUS(status); |
|
331 |
} else if (WIFSIGNALED(status)) { |
|
332 |
/* The child exited because of a signal. |
|
333 |
* The best value to return is 0x80 + signal number, |
|
334 |
* because that is what all Unix shells do, and because |
|
335 |
* it allows callers to distinguish between process exit and |
|
336 |
* process death by signal. |
|
337 |
* Unfortunately, the historical behavior on Solaris is to return |
|
338 |
* the signal number, and we preserve this for compatibility. */ |
|
339 |
#ifdef __solaris__ |
|
340 |
return WTERMSIG(status); |
|
341 |
#else |
|
342 |
return 0x80 + WTERMSIG(status); |
|
343 |
#endif |
|
344 |
} else { |
|
345 |
/* |
|
346 |
* Unknown exit code; pass it through. |
|
347 |
*/ |
|
348 |
return status; |
|
349 |
} |
|
350 |
} |
|
351 |
||
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
352 |
static ssize_t |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
353 |
restartableWrite(int fd, const void *buf, size_t count) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
354 |
{ |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
355 |
ssize_t result; |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
356 |
RESTARTABLE(write(fd, buf, count), result); |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
357 |
return result; |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
358 |
} |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
359 |
|
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
360 |
static int |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
361 |
restartableDup2(int fd_from, int fd_to) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
362 |
{ |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
363 |
int err; |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
364 |
RESTARTABLE(dup2(fd_from, fd_to), err); |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
365 |
return err; |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
366 |
} |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
367 |
|
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
368 |
static int |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
369 |
restartableClose(int fd) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
370 |
{ |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
371 |
int err; |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
372 |
RESTARTABLE(close(fd), err); |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
373 |
return err; |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
374 |
} |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
375 |
|
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
376 |
static int |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
377 |
closeSafely(int fd) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
378 |
{ |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
379 |
return (fd == -1) ? 0 : restartableClose(fd); |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
380 |
} |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
381 |
|
2 | 382 |
static int |
1936
66e7f98f4dde
6798822: (process) Non-portable use of isdigit in src/solaris/native/java/lang/UNIXProcess_md.c
martin
parents:
50
diff
changeset
|
383 |
isAsciiDigit(char c) |
66e7f98f4dde
6798822: (process) Non-portable use of isdigit in src/solaris/native/java/lang/UNIXProcess_md.c
martin
parents:
50
diff
changeset
|
384 |
{ |
66e7f98f4dde
6798822: (process) Non-portable use of isdigit in src/solaris/native/java/lang/UNIXProcess_md.c
martin
parents:
50
diff
changeset
|
385 |
return c >= '0' && c <= '9'; |
66e7f98f4dde
6798822: (process) Non-portable use of isdigit in src/solaris/native/java/lang/UNIXProcess_md.c
martin
parents:
50
diff
changeset
|
386 |
} |
66e7f98f4dde
6798822: (process) Non-portable use of isdigit in src/solaris/native/java/lang/UNIXProcess_md.c
martin
parents:
50
diff
changeset
|
387 |
|
66e7f98f4dde
6798822: (process) Non-portable use of isdigit in src/solaris/native/java/lang/UNIXProcess_md.c
martin
parents:
50
diff
changeset
|
388 |
static int |
2 | 389 |
closeDescriptors(void) |
390 |
{ |
|
391 |
DIR *dp; |
|
392 |
struct dirent64 *dirp; |
|
393 |
int from_fd = FAIL_FILENO + 1; |
|
394 |
||
395 |
/* We're trying to close all file descriptors, but opendir() might |
|
396 |
* itself be implemented using a file descriptor, and we certainly |
|
397 |
* don't want to close that while it's in use. We assume that if |
|
398 |
* opendir() is implemented using a file descriptor, then it uses |
|
399 |
* the lowest numbered file descriptor, just like open(). So we |
|
400 |
* close a couple explicitly. */ |
|
401 |
||
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
402 |
restartableClose(from_fd); /* for possible use by opendir() */ |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
403 |
restartableClose(from_fd + 1); /* another one for good luck */ |
2 | 404 |
|
405 |
if ((dp = opendir("/proc/self/fd")) == NULL) |
|
406 |
return 0; |
|
407 |
||
408 |
/* We use readdir64 instead of readdir to work around Solaris bug |
|
409 |
* 6395699: /proc/self/fd fails to report file descriptors >= 1024 on Solaris 9 |
|
410 |
*/ |
|
411 |
while ((dirp = readdir64(dp)) != NULL) { |
|
412 |
int fd; |
|
1936
66e7f98f4dde
6798822: (process) Non-portable use of isdigit in src/solaris/native/java/lang/UNIXProcess_md.c
martin
parents:
50
diff
changeset
|
413 |
if (isAsciiDigit(dirp->d_name[0]) && |
2 | 414 |
(fd = strtol(dirp->d_name, NULL, 10)) >= from_fd + 2) |
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
415 |
restartableClose(fd); |
2 | 416 |
} |
417 |
||
418 |
closedir(dp); |
|
419 |
||
420 |
return 1; |
|
421 |
} |
|
422 |
||
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
423 |
static int |
2 | 424 |
moveDescriptor(int fd_from, int fd_to) |
425 |
{ |
|
426 |
if (fd_from != fd_to) { |
|
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
427 |
if ((restartableDup2(fd_from, fd_to) == -1) || |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
428 |
(restartableClose(fd_from) == -1)) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
429 |
return -1; |
2 | 430 |
} |
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
431 |
return 0; |
2 | 432 |
} |
433 |
||
434 |
static const char * |
|
435 |
getBytes(JNIEnv *env, jbyteArray arr) |
|
436 |
{ |
|
437 |
return arr == NULL ? NULL : |
|
438 |
(const char*) (*env)->GetByteArrayElements(env, arr, NULL); |
|
439 |
} |
|
440 |
||
441 |
static void |
|
442 |
releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr) |
|
443 |
{ |
|
444 |
if (parr != NULL) |
|
445 |
(*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT); |
|
446 |
} |
|
447 |
||
448 |
static void |
|
449 |
initVectorFromBlock(const char**vector, const char* block, int count) |
|
450 |
{ |
|
451 |
int i; |
|
452 |
const char *p; |
|
453 |
for (i = 0, p = block; i < count; i++) { |
|
454 |
/* Invariant: p always points to the start of a C string. */ |
|
455 |
vector[i] = p; |
|
456 |
while (*(p++)); |
|
457 |
} |
|
458 |
vector[count] = NULL; |
|
459 |
} |
|
460 |
||
461 |
static void |
|
462 |
throwIOException(JNIEnv *env, int errnum, const char *defaultDetail) |
|
463 |
{ |
|
464 |
static const char * const format = "error=%d, %s"; |
|
465 |
const char *detail = defaultDetail; |
|
466 |
char *errmsg; |
|
467 |
jstring s; |
|
468 |
||
469 |
if (errnum != 0) { |
|
470 |
const char *s = strerror(errnum); |
|
471 |
if (strcmp(s, "Unknown error") != 0) |
|
472 |
detail = s; |
|
473 |
} |
|
474 |
/* ASCII Decimal representation uses 2.4 times as many bits as binary. */ |
|
475 |
errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum)); |
|
476 |
sprintf(errmsg, format, errnum, detail); |
|
477 |
s = JNU_NewStringPlatform(env, errmsg); |
|
478 |
if (s != NULL) { |
|
479 |
jobject x = JNU_NewObjectByName(env, "java/io/IOException", |
|
480 |
"(Ljava/lang/String;)V", s); |
|
481 |
if (x != NULL) |
|
482 |
(*env)->Throw(env, x); |
|
483 |
} |
|
484 |
free(errmsg); |
|
485 |
} |
|
486 |
||
487 |
#ifdef DEBUG_PROCESS |
|
488 |
/* Debugging process code is difficult; where to write debug output? */ |
|
489 |
static void |
|
490 |
debugPrint(char *format, ...) |
|
491 |
{ |
|
492 |
FILE *tty = fopen("/dev/tty", "w"); |
|
493 |
va_list ap; |
|
494 |
va_start(ap, format); |
|
495 |
vfprintf(tty, format, ap); |
|
496 |
va_end(ap); |
|
497 |
fclose(tty); |
|
498 |
} |
|
499 |
#endif /* DEBUG_PROCESS */ |
|
500 |
||
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
501 |
/** |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
502 |
* Exec FILE as a traditional Bourne shell script (i.e. one without #!). |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
503 |
* If we could do it over again, we would probably not support such an ancient |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
504 |
* misfeature, but compatibility wins over sanity. The original support for |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
505 |
* this was imported accidentally from execvp(). |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
506 |
*/ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
507 |
static void |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
508 |
execve_as_traditional_shell_script(const char *file, |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
509 |
const char *argv[], |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
510 |
const char *const envp[]) |
2 | 511 |
{ |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
512 |
/* Use the extra word of space provided for us in argv by caller. */ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
513 |
const char *argv0 = argv[0]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
514 |
const char *const *end = argv; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
515 |
while (*end != NULL) |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
516 |
++end; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
517 |
memmove(argv+2, argv+1, (end-argv) * sizeof (*end)); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
518 |
argv[0] = "/bin/sh"; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
519 |
argv[1] = file; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
520 |
execve(argv[0], (char **) argv, (char **) envp); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
521 |
/* Can't even exec /bin/sh? Big trouble, but let's soldier on... */ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
522 |
memmove(argv+1, argv+2, (end-argv) * sizeof (*end)); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
523 |
argv[0] = argv0; |
2 | 524 |
} |
525 |
||
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
526 |
/** |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
527 |
* Like execve(2), except that in case of ENOEXEC, FILE is assumed to |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
528 |
* be a shell script and the system default shell is invoked to run it. |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
529 |
*/ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
530 |
static void |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
531 |
execve_with_shell_fallback(const char *file, |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
532 |
const char *argv[], |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
533 |
const char *const envp[]) |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
534 |
{ |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
535 |
#if START_CHILD_USE_CLONE || START_CHILD_USE_VFORK |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
536 |
/* shared address space; be very careful. */ |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
537 |
execve(file, (char **) argv, (char **) envp); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
538 |
if (errno == ENOEXEC) |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
539 |
execve_as_traditional_shell_script(file, argv, envp); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
540 |
#else |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
541 |
/* unshared address space; we can mutate environ. */ |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
542 |
environ = (char **) envp; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
543 |
execvp(file, (char **) argv); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
544 |
#endif |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
545 |
} |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
546 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
547 |
/** |
3421
e3af585364e7
6866719: Rename execvpe to avoid symbol clash with glibc 2.10
martin
parents:
2948
diff
changeset
|
548 |
* 'execvpe' should have been included in the Unix standards, |
e3af585364e7
6866719: Rename execvpe to avoid symbol clash with glibc 2.10
martin
parents:
2948
diff
changeset
|
549 |
* and is a GNU extension in glibc 2.10. |
e3af585364e7
6866719: Rename execvpe to avoid symbol clash with glibc 2.10
martin
parents:
2948
diff
changeset
|
550 |
* |
e3af585364e7
6866719: Rename execvpe to avoid symbol clash with glibc 2.10
martin
parents:
2948
diff
changeset
|
551 |
* JDK_execvpe is identical to execvp, except that the child environment is |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
552 |
* specified via the 3rd argument instead of being inherited from environ. |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
553 |
*/ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
554 |
static void |
3421
e3af585364e7
6866719: Rename execvpe to avoid symbol clash with glibc 2.10
martin
parents:
2948
diff
changeset
|
555 |
JDK_execvpe(const char *file, |
e3af585364e7
6866719: Rename execvpe to avoid symbol clash with glibc 2.10
martin
parents:
2948
diff
changeset
|
556 |
const char *argv[], |
e3af585364e7
6866719: Rename execvpe to avoid symbol clash with glibc 2.10
martin
parents:
2948
diff
changeset
|
557 |
const char *const envp[]) |
2 | 558 |
{ |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
559 |
if (envp == NULL || (char **) envp == environ) { |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
560 |
execvp(file, (char **) argv); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
561 |
return; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
562 |
} |
2 | 563 |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
564 |
if (*file == '\0') { |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
565 |
errno = ENOENT; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
566 |
return; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
567 |
} |
2 | 568 |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
569 |
if (strchr(file, '/') != NULL) { |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
570 |
execve_with_shell_fallback(file, argv, envp); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
571 |
} else { |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
572 |
/* We must search PATH (parent's, not child's) */ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
573 |
char expanded_file[PATH_MAX]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
574 |
int filelen = strlen(file); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
575 |
int sticky_errno = 0; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
576 |
const char * const * dirs; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
577 |
for (dirs = parentPathv; *dirs; dirs++) { |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
578 |
const char * dir = *dirs; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
579 |
int dirlen = strlen(dir); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
580 |
if (filelen + dirlen + 1 >= PATH_MAX) { |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
581 |
errno = ENAMETOOLONG; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
582 |
continue; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
583 |
} |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
584 |
memcpy(expanded_file, dir, dirlen); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
585 |
memcpy(expanded_file + dirlen, file, filelen); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
586 |
expanded_file[dirlen + filelen] = '\0'; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
587 |
execve_with_shell_fallback(expanded_file, argv, envp); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
588 |
/* There are 3 responses to various classes of errno: |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
589 |
* return immediately, continue (especially for ENOENT), |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
590 |
* or continue with "sticky" errno. |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
591 |
* |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
592 |
* From exec(3): |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
593 |
* |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
594 |
* If permission is denied for a file (the attempted |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
595 |
* execve returned EACCES), these functions will continue |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
596 |
* searching the rest of the search path. If no other |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
597 |
* file is found, however, they will return with the |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
598 |
* global variable errno set to EACCES. |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
599 |
*/ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
600 |
switch (errno) { |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
601 |
case EACCES: |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
602 |
sticky_errno = errno; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
603 |
/* FALLTHRU */ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
604 |
case ENOENT: |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
605 |
case ENOTDIR: |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
606 |
#ifdef ELOOP |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
607 |
case ELOOP: |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
608 |
#endif |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
609 |
#ifdef ESTALE |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
610 |
case ESTALE: |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
611 |
#endif |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
612 |
#ifdef ENODEV |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
613 |
case ENODEV: |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
614 |
#endif |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
615 |
#ifdef ETIMEDOUT |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
616 |
case ETIMEDOUT: |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
617 |
#endif |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
618 |
break; /* Try other directories in PATH */ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
619 |
default: |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
620 |
return; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
621 |
} |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
622 |
} |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
623 |
if (sticky_errno != 0) |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
624 |
errno = sticky_errno; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
625 |
} |
2 | 626 |
} |
627 |
||
50
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
628 |
/* |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
629 |
* Reads nbyte bytes from file descriptor fd into buf, |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
630 |
* The read operation is retried in case of EINTR or partial reads. |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
631 |
* |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
632 |
* Returns number of bytes read (normally nbyte, but may be less in |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
633 |
* case of EOF). In case of read errors, returns -1 and sets errno. |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
634 |
*/ |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
635 |
static ssize_t |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
636 |
readFully(int fd, void *buf, size_t nbyte) |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
637 |
{ |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
638 |
ssize_t remaining = nbyte; |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
639 |
for (;;) { |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
640 |
ssize_t n = read(fd, buf, remaining); |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
641 |
if (n == 0) { |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
642 |
return nbyte - remaining; |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
643 |
} else if (n > 0) { |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
644 |
remaining -= n; |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
645 |
if (remaining <= 0) |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
646 |
return nbyte; |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
647 |
/* We were interrupted in the middle of reading the bytes. |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
648 |
* Unlikely, but possible. */ |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
649 |
buf = (void *) (((char *)buf) + n); |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
650 |
} else if (errno == EINTR) { |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
651 |
/* Strange signals like SIGJVM1 are possible at any time. |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
652 |
* See http://www.dreamsongs.com/WorseIsBetter.html */ |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
653 |
} else { |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
654 |
return -1; |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
655 |
} |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
656 |
} |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
657 |
} |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
658 |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
659 |
typedef struct _ChildStuff |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
660 |
{ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
661 |
int in[2]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
662 |
int out[2]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
663 |
int err[2]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
664 |
int fail[2]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
665 |
int fds[3]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
666 |
const char **argv; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
667 |
const char **envv; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
668 |
const char *pdir; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
669 |
jboolean redirectErrorStream; |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
670 |
#if START_CHILD_USE_CLONE |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
671 |
void *clone_stack; |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
672 |
#endif |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
673 |
} ChildStuff; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
674 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
675 |
static void |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
676 |
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
|
677 |
{ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
678 |
to[0] = from[0]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
679 |
to[1] = from[1]; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
680 |
} |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
681 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
682 |
/** |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
683 |
* Child process after a successful fork() or clone(). |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
684 |
* This function must not return, and must be prepared for either all |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
685 |
* of its address space to be shared with its parent, or to be a copy. |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
686 |
* It must not modify global variables such as "environ". |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
687 |
*/ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
688 |
static int |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
689 |
childProcess(void *arg) |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
690 |
{ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
691 |
const ChildStuff* p = (const ChildStuff*) arg; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
692 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
693 |
/* Close the parent sides of the pipes. |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
694 |
Closing pipe fds here is redundant, since closeDescriptors() |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
695 |
would do it anyways, but a little paranoia is a good thing. */ |
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
696 |
if ((closeSafely(p->in[1]) == -1) || |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
697 |
(closeSafely(p->out[0]) == -1) || |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
698 |
(closeSafely(p->err[0]) == -1) || |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
699 |
(closeSafely(p->fail[0]) == -1)) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
700 |
goto WhyCantJohnnyExec; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
701 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
702 |
/* Give the child sides of the pipes the right fileno's. */ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
703 |
/* Note: it is possible for in[0] == 0 */ |
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
704 |
if ((moveDescriptor(p->in[0] != -1 ? p->in[0] : p->fds[0], |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
705 |
STDIN_FILENO) == -1) || |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
706 |
(moveDescriptor(p->out[1]!= -1 ? p->out[1] : p->fds[1], |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
707 |
STDOUT_FILENO) == -1)) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
708 |
goto WhyCantJohnnyExec; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
709 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
710 |
if (p->redirectErrorStream) { |
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
711 |
if ((closeSafely(p->err[1]) == -1) || |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
712 |
(restartableDup2(STDOUT_FILENO, STDERR_FILENO) == -1)) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
713 |
goto WhyCantJohnnyExec; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
714 |
} else { |
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
715 |
if (moveDescriptor(p->err[1] != -1 ? p->err[1] : p->fds[2], |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
716 |
STDERR_FILENO) == -1) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
717 |
goto WhyCantJohnnyExec; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
718 |
} |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
719 |
|
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
720 |
if (moveDescriptor(p->fail[1], FAIL_FILENO) == -1) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
721 |
goto WhyCantJohnnyExec; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
722 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
723 |
/* close everything */ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
724 |
if (closeDescriptors() == 0) { /* failed, close the old way */ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
725 |
int max_fd = (int)sysconf(_SC_OPEN_MAX); |
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
726 |
int fd; |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
727 |
for (fd = FAIL_FILENO + 1; fd < max_fd; fd++) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
728 |
if (restartableClose(fd) == -1 && errno != EBADF) |
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
729 |
goto WhyCantJohnnyExec; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
730 |
} |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
731 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
732 |
/* change to the new working directory */ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
733 |
if (p->pdir != NULL && chdir(p->pdir) < 0) |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
734 |
goto WhyCantJohnnyExec; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
735 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
736 |
if (fcntl(FAIL_FILENO, F_SETFD, FD_CLOEXEC) == -1) |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
737 |
goto WhyCantJohnnyExec; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
738 |
|
3421
e3af585364e7
6866719: Rename execvpe to avoid symbol clash with glibc 2.10
martin
parents:
2948
diff
changeset
|
739 |
JDK_execvpe(p->argv[0], p->argv, p->envv); |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
740 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
741 |
WhyCantJohnnyExec: |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
742 |
/* We used to go to an awful lot of trouble to predict whether the |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
743 |
* child would fail, but there is no reliable way to predict the |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
744 |
* success of an operation without *trying* it, and there's no way |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
745 |
* to try a chdir or exec in the parent. Instead, all we need is a |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
746 |
* way to communicate any failure back to the parent. Easy; we just |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
747 |
* send the errno back to the parent over a pipe in case of failure. |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
748 |
* The tricky thing is, how do we communicate the *success* of exec? |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
749 |
* We use FD_CLOEXEC together with the fact that a read() on a pipe |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
750 |
* yields EOF when the write ends (we have two of them!) are closed. |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
751 |
*/ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
752 |
{ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
753 |
int errnum = errno; |
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
754 |
restartableWrite(FAIL_FILENO, &errnum, sizeof(errnum)); |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
755 |
} |
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
756 |
restartableClose(FAIL_FILENO); |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
757 |
_exit(-1); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
758 |
return 0; /* Suppress warning "no return value from function" */ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
759 |
} |
2 | 760 |
|
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
761 |
/** |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
762 |
* Start a child process running function childProcess. |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
763 |
* This function only returns in the parent. |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
764 |
* We are unusually paranoid; use of clone/vfork is |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
765 |
* 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
|
766 |
*/ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
767 |
#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
|
768 |
__attribute_noinline__ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
769 |
#endif |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
770 |
static pid_t |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
771 |
startChild(ChildStuff *c) { |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
772 |
#if START_CHILD_USE_CLONE |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
773 |
#define START_CHILD_CLONE_STACK_SIZE (64 * 1024) |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
774 |
/* |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
775 |
* See clone(2). |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
776 |
* Instead of worrying about which direction the stack grows, just |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
777 |
* allocate twice as much and start the stack in the middle. |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
778 |
*/ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
779 |
if ((c->clone_stack = malloc(2 * START_CHILD_CLONE_STACK_SIZE)) == NULL) |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
780 |
/* errno will be set to ENOMEM */ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
781 |
return -1; |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
782 |
return clone(childProcess, |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
783 |
c->clone_stack + START_CHILD_CLONE_STACK_SIZE, |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
784 |
CLONE_VFORK | CLONE_VM | SIGCHLD, c); |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
785 |
#else |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
786 |
#if START_CHILD_USE_VFORK |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
787 |
/* |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
788 |
* 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
|
789 |
* 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
|
790 |
* 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
|
791 |
* 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
|
792 |
*/ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
793 |
volatile pid_t resultPid = vfork(); |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
794 |
#else |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
795 |
/* |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
796 |
* 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
|
797 |
* 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
|
798 |
* 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
|
799 |
* behavior for fork(). |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
800 |
*/ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
801 |
pid_t resultPid = fork(); |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
802 |
#endif |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
803 |
if (resultPid == 0) |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
804 |
childProcess(c); |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
805 |
assert(resultPid != 0); /* childProcess never returns */ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
806 |
return resultPid; |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
807 |
#endif /* ! START_CHILD_USE_CLONE */ |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
808 |
} |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
809 |
|
2 | 810 |
JNIEXPORT jint JNICALL |
811 |
Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, |
|
812 |
jobject process, |
|
813 |
jbyteArray prog, |
|
814 |
jbyteArray argBlock, jint argc, |
|
815 |
jbyteArray envBlock, jint envc, |
|
816 |
jbyteArray dir, |
|
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
817 |
jintArray std_fds, |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
818 |
jboolean redirectErrorStream) |
2 | 819 |
{ |
820 |
int errnum; |
|
821 |
int resultPid = -1; |
|
822 |
int in[2], out[2], err[2], fail[2]; |
|
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
823 |
jint *fds = NULL; |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
824 |
const char *pprog = NULL; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
825 |
const char *pargBlock = NULL; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
826 |
const char *penvBlock = NULL; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
827 |
ChildStuff *c; |
2 | 828 |
|
829 |
in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1; |
|
830 |
||
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
831 |
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
|
832 |
c->argv = NULL; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
833 |
c->envv = NULL; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
834 |
c->pdir = NULL; |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
835 |
#if START_CHILD_USE_CLONE |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
836 |
c->clone_stack = NULL; |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
837 |
#endif |
2 | 838 |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
839 |
/* 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
|
840 |
* 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
|
841 |
* execve_as_traditional_shell_script. |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
842 |
*/ |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
843 |
assert(prog != NULL && argBlock != NULL); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
844 |
if ((pprog = getBytes(env, prog)) == NULL) goto Catch; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
845 |
if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
846 |
if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
847 |
c->argv[0] = pprog; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
848 |
initVectorFromBlock(c->argv+1, pargBlock, argc); |
2 | 849 |
|
850 |
if (envBlock != NULL) { |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
851 |
/* 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
|
852 |
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
|
853 |
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
|
854 |
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
|
855 |
} |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
856 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
857 |
if (dir != NULL) { |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
858 |
if ((c->pdir = getBytes(env, dir)) == NULL) goto Catch; |
2 | 859 |
} |
860 |
||
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
861 |
assert(std_fds != NULL); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
862 |
fds = (*env)->GetIntArrayElements(env, std_fds, NULL); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
863 |
if (fds == NULL) goto Catch; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
864 |
|
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
865 |
if ((fds[0] == -1 && pipe(in) < 0) || |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
866 |
(fds[1] == -1 && pipe(out) < 0) || |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
867 |
(fds[2] == -1 && pipe(err) < 0) || |
2 | 868 |
(pipe(fail) < 0)) { |
869 |
throwIOException(env, errno, "Bad file descriptor"); |
|
870 |
goto Catch; |
|
871 |
} |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
872 |
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
|
873 |
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
|
874 |
c->fds[2] = fds[2]; |
2 | 875 |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
876 |
copyPipe(in, c->in); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
877 |
copyPipe(out, c->out); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
878 |
copyPipe(err, c->err); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
879 |
copyPipe(fail, c->fail); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
880 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
881 |
c->redirectErrorStream = redirectErrorStream; |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
882 |
|
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
883 |
resultPid = startChild(c); |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
884 |
assert(resultPid != 0); |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
885 |
|
2 | 886 |
if (resultPid < 0) { |
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
887 |
throwIOException(env, errno, START_CHILD_SYSTEM_CALL " failed"); |
2 | 888 |
goto Catch; |
889 |
} |
|
890 |
||
3431
e9cb95a39e3e
6856590: (process) Use RESTARTABLE in UNIXProcess_md.c
martin
parents:
3430
diff
changeset
|
891 |
restartableClose(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */ |
50
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
892 |
|
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
893 |
switch (readFully(fail[0], &errnum, sizeof(errnum))) { |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
894 |
case 0: break; /* Exec succeeded */ |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
895 |
case sizeof(errnum): |
2 | 896 |
waitpid(resultPid, NULL, 0); |
897 |
throwIOException(env, errnum, "Exec failed"); |
|
898 |
goto Catch; |
|
50
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
899 |
default: |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
900 |
throwIOException(env, errno, "Read failed"); |
a437b3f9d7f4
6671051: (process) Runtime.exec() hangs if signalled during fork/exec
martin
parents:
48
diff
changeset
|
901 |
goto Catch; |
2 | 902 |
} |
903 |
||
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
904 |
fds[0] = (in [1] != -1) ? in [1] : -1; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
905 |
fds[1] = (out[0] != -1) ? out[0] : -1; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
906 |
fds[2] = (err[0] != -1) ? err[0] : -1; |
2 | 907 |
|
908 |
Finally: |
|
3430
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
909 |
#if START_CHILD_USE_CLONE |
8d6d03175761
6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion
martin
parents:
3421
diff
changeset
|
910 |
free(c->clone_stack); |
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
911 |
#endif |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
912 |
|
2 | 913 |
/* Always clean up the child's side of the pipes */ |
914 |
closeSafely(in [0]); |
|
915 |
closeSafely(out[1]); |
|
916 |
closeSafely(err[1]); |
|
917 |
||
918 |
/* Always clean up fail descriptors */ |
|
919 |
closeSafely(fail[0]); |
|
920 |
closeSafely(fail[1]); |
|
921 |
||
922 |
releaseBytes(env, prog, pprog); |
|
923 |
releaseBytes(env, argBlock, pargBlock); |
|
924 |
releaseBytes(env, envBlock, penvBlock); |
|
2946
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
925 |
releaseBytes(env, dir, c->pdir); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
926 |
|
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
927 |
free(c->argv); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
928 |
free(c->envv); |
f95752c3204a
6850720: (process) Use clone(CLONE_VM), not fork, on Linux to avoid swap exhaustion
martin
parents:
1936
diff
changeset
|
929 |
free(c); |
2 | 930 |
|
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
931 |
if (fds != NULL) |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
932 |
(*env)->ReleaseIntArrayElements(env, std_fds, fds, 0); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
933 |
|
2 | 934 |
return resultPid; |
935 |
||
936 |
Catch: |
|
937 |
/* Clean up the parent's side of the pipes in case of failure only */ |
|
938 |
closeSafely(in [1]); |
|
939 |
closeSafely(out[0]); |
|
940 |
closeSafely(err[0]); |
|
941 |
goto Finally; |
|
942 |
} |
|
943 |
||
944 |
JNIEXPORT void JNICALL |
|
945 |
Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env, jobject junk, jint pid) |
|
946 |
{ |
|
947 |
kill(pid, SIGTERM); |
|
948 |
} |