47
48 /**
49 * java.lang.Process subclass in the UNIX environment.
50 *
51 * @author Mario Wolczko and Ross Knippel.
52 * @author Konstantin Kladko (ported to Bsd)
53 * @author Martin Buchholz
54 */
55 final class UNIXProcess extends Process {
56 private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
57 = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
58
59 private final int pid;
60 private int exitcode;
61 private boolean hasExited;
62
63 private /* final */ OutputStream stdin;
64 private /* final */ InputStream stdout;
65 private /* final */ InputStream stderr;
66
67 /* this is for the reaping thread */
68 private native int waitForProcessExit(int pid);
69
70 /**
71 * Create a process using fork(2) and exec(2).
72 *
73 * @param fds an array of three file descriptors.
74 * Indexes 0, 1, and 2 correspond to standard input,
75 * standard output and standard error, respectively. On
76 * input, a value of -1 means to create a pipe to connect
77 * child and parent processes. On output, a value which
78 * is not -1 is the parent pipe fd corresponding to the
79 * pipe which has been created. An element of this array
80 * is -1 on input if and only if it is <em>not</em> -1 on
81 * output.
82 * @return the pid of the subprocess
83 */
84 private native int forkAndExec(byte[] prog,
85 byte[] argBlock, int argc,
86 byte[] envBlock, int envc,
87 byte[] dir,
88 int[] fds,
89 boolean redirectErrorStream)
90 throws IOException;
91
92 /**
93 * The thread factory used to create "process reaper" daemon threads.
94 */
95 private static class ProcessReaperThreadFactory implements ThreadFactory {
96 private final static ThreadGroup group = getRootThreadGroup();
97
98 private static ThreadGroup getRootThreadGroup() {
99 return doPrivileged(new PrivilegedAction<ThreadGroup> () {
100 public ThreadGroup run() {
101 ThreadGroup root = Thread.currentThread().getThreadGroup();
102 while (root.getParent() != null)
103 root = root.getParent();
104 return root;
116 }
117
118 /**
119 * The thread pool of "process reaper" daemon threads.
120 */
121 private static final Executor processReaperExecutor =
122 doPrivileged(new PrivilegedAction<Executor>() {
123 public Executor run() {
124 return Executors.newCachedThreadPool
125 (new ProcessReaperThreadFactory());
126 }});
127
128 UNIXProcess(final byte[] prog,
129 final byte[] argBlock, final int argc,
130 final byte[] envBlock, final int envc,
131 final byte[] dir,
132 final int[] fds,
133 final boolean redirectErrorStream)
134 throws IOException {
135
136 pid = forkAndExec(prog,
137 argBlock, argc,
138 envBlock, envc,
139 dir,
140 fds,
141 redirectErrorStream);
142
143 try {
144 doPrivileged(new PrivilegedExceptionAction<Void>() {
145 public Void run() throws IOException {
146 initStreams(fds);
147 return null;
148 }});
149 } catch (PrivilegedActionException ex) {
150 throw (IOException) ex.getException();
151 }
152 }
153
154 static FileDescriptor newFileDescriptor(int fd) {
155 FileDescriptor fileDescriptor = new FileDescriptor();
156 fdAccess.set(fileDescriptor, fd);
|
47
48 /**
49 * java.lang.Process subclass in the UNIX environment.
50 *
51 * @author Mario Wolczko and Ross Knippel.
52 * @author Konstantin Kladko (ported to Bsd)
53 * @author Martin Buchholz
54 */
55 final class UNIXProcess extends Process {
56 private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
57 = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
58
59 private final int pid;
60 private int exitcode;
61 private boolean hasExited;
62
63 private /* final */ OutputStream stdin;
64 private /* final */ InputStream stdout;
65 private /* final */ InputStream stderr;
66
67 private static String javahome;
68 private static String arch;
69 private static String helperpath;
70
71 enum LaunchMechanism {
72 CLONE(1), FORK(2),
73 VFORK(3), POSIX_SPAWN(4);
74
75 private int value;
76 LaunchMechanism(int x) {value = x;}
77 };
78
79 /* On BSD, the default is to spawn */
80 private static LaunchMechanism launchMechanism = LaunchMechanism.POSIX_SPAWN;
81
82 static {
83 AccessController.doPrivileged(new PrivilegedAction<Void>() {
84 public Void run() {
85 String javahome = System.getProperty("java.home");
86 String osarch = System.getProperty("os.arch");
87
88 helperpath = javahome + "/lib/jspawnhelper";
89 String s = System.getProperty("jdk.lang.Process.launchMechanism");
90 if (s != null && !s.equals("POSIX_SPAWN")) {
91 if (s.equals("FORK")) {
92 launchMechanism = LaunchMechanism.FORK;
93 } else {
94 throw new Error(s + " is not a supported " +
95 "process launch mechanism on this platform.");
96 }
97 }
98 return null;
99 }
100 });
101 }
102
103 /* this is for the reaping thread */
104 private native int waitForProcessExit(int pid);
105
106 /**
107 * Create a process. Depending on the mode flag, this is done by
108 * one of the following mechanisms.
109 * - fork(2) and exec(2)
110 * - vfork(2) and exec(2)
111 * - posix_spawn(2)
112 *
113 * @param fds an array of three file descriptors.
114 * Indexes 0, 1, and 2 correspond to standard input,
115 * standard output and standard error, respectively. On
116 * input, a value of -1 means to create a pipe to connect
117 * child and parent processes. On output, a value which
118 * is not -1 is the parent pipe fd corresponding to the
119 * pipe which has been created. An element of this array
120 * is -1 on input if and only if it is <em>not</em> -1 on
121 * output.
122 * @return the pid of the subprocess
123 */
124 private native int forkAndExec(int mode, byte[] prog,
125 byte[] argBlock, int argc,
126 byte[] envBlock, int envc,
127 byte[] dir,
128 int[] fds,
129 boolean redirectErrorStream)
130 throws IOException;
131
132 /**
133 * The thread factory used to create "process reaper" daemon threads.
134 */
135 private static class ProcessReaperThreadFactory implements ThreadFactory {
136 private final static ThreadGroup group = getRootThreadGroup();
137
138 private static ThreadGroup getRootThreadGroup() {
139 return doPrivileged(new PrivilegedAction<ThreadGroup> () {
140 public ThreadGroup run() {
141 ThreadGroup root = Thread.currentThread().getThreadGroup();
142 while (root.getParent() != null)
143 root = root.getParent();
144 return root;
156 }
157
158 /**
159 * The thread pool of "process reaper" daemon threads.
160 */
161 private static final Executor processReaperExecutor =
162 doPrivileged(new PrivilegedAction<Executor>() {
163 public Executor run() {
164 return Executors.newCachedThreadPool
165 (new ProcessReaperThreadFactory());
166 }});
167
168 UNIXProcess(final byte[] prog,
169 final byte[] argBlock, final int argc,
170 final byte[] envBlock, final int envc,
171 final byte[] dir,
172 final int[] fds,
173 final boolean redirectErrorStream)
174 throws IOException {
175
176 pid = forkAndExec(launchMechanism.value,
177 prog,
178 argBlock, argc,
179 envBlock, envc,
180 dir,
181 fds,
182 redirectErrorStream);
183
184 try {
185 doPrivileged(new PrivilegedExceptionAction<Void>() {
186 public Void run() throws IOException {
187 initStreams(fds);
188 return null;
189 }});
190 } catch (PrivilegedActionException ex) {
191 throw (IOException) ex.getException();
192 }
193 }
194
195 static FileDescriptor newFileDescriptor(int fd) {
196 FileDescriptor fileDescriptor = new FileDescriptor();
197 fdAccess.set(fileDescriptor, fd);
|