Skip to content

Commit d51f840

Browse files
VMProcess: Poll faster for reapable chidren if there are threads waiting
If there are threads currently waiting in waitFor() or destroy(), have the reaper thread switch to a shorter delay when polling for reapable children. By default, set this "fast polling" delay to 100 ms. This can be controlled via the gnu.lang.process.fastPolling system property. Closes #23 (BZ#111587)
1 parent 4fa963f commit d51f840

File tree

1 file changed

+41
-9
lines changed

1 file changed

+41
-9
lines changed

vm/reference/java/lang/VMProcess.java

+41-9
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ final class VMProcess extends Process
7979
// New processes waiting to be spawned by processThread.
8080
static final LinkedList workList = new LinkedList();
8181

82+
// Number of threads waiting in waitFor() or destroy()
83+
static int waiters;
84+
8285
// Return values set by nativeReap() when a child is reaped.
8386
// These are only accessed by processThread so no locking required.
8487
static long reapedPid;
@@ -109,6 +112,18 @@ private static class ProcessThread extends Thread
109112
// Max time (in ms) we'll delay before trying to reap another child.
110113
private static final int MAX_REAP_DELAY = 1000;
111114

115+
// Default polling delay (in ms) in "fast polling mode", i.e. when
116+
// there are threads waiting in waitFor() or destroy().
117+
// Can be changed using the gnu.lang.process.fastPolling system property.
118+
private static final int DEFAULT_FAST_POLLING_DELAY = 100;
119+
120+
// Actual polling delay in fast polling mode
121+
private static final int fastPollingDelay;
122+
static
123+
{
124+
fastPollingDelay = Integer.getInteger("gnu.lang.process.fastPolling", DEFAULT_FAST_POLLING_DELAY);
125+
}
126+
112127
// Processes created but not yet terminated; maps Long(pid) -> VMProcess
113128
// Only used in run() and spawn() method from this Thread, so no locking.
114129
private final HashMap activeMap = new HashMap();
@@ -180,7 +195,7 @@ public void run()
180195

181196
try
182197
{
183-
workList.wait(MAX_REAP_DELAY);
198+
workList.wait(waiters > 0 ? fastPollingDelay : MAX_REAP_DELAY);
184199
}
185200
catch (InterruptedException e)
186201
{
@@ -330,15 +345,35 @@ public InputStream getErrorStream()
330345
return stderr;
331346
}
332347

333-
public synchronized int waitFor() throws InterruptedException
348+
private void addWaiter()
334349
{
335350
synchronized (workList)
336351
{
352+
waiters++;
337353
workList.notify();
338354
}
355+
}
356+
357+
private void removeWaiter()
358+
{
359+
synchronized (workList)
360+
{
361+
waiters--;
362+
}
363+
}
339364

340-
while (state != TERMINATED)
341-
wait();
365+
public synchronized int waitFor() throws InterruptedException
366+
{
367+
try
368+
{
369+
addWaiter();
370+
while (state != TERMINATED)
371+
wait();
372+
}
373+
finally
374+
{
375+
removeWaiter();
376+
}
342377
return exitValue;
343378
}
344379

@@ -356,12 +391,9 @@ public synchronized void destroy()
356391

357392
nativeKill(pid);
358393

359-
synchronized (workList)
360-
{
361-
workList.notify();
362-
}
363-
394+
addWaiter();
364395
waitForStateUninterruptibly(TERMINATED, false);
396+
removeWaiter();
365397
}
366398

367399
private void waitForStateUninterruptibly(int state, boolean eq)

0 commit comments

Comments
 (0)