1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 17:05:26 +02:00

Bug 574131: Do not concurrently call Spawner#destroy()

As the Object#wait() voids the synchronization, more threads can call
destroy() before the Reaper thread has identified that the process
exited or the timeout occured.
The change ensures that only one call actually raises the signal while
the others are NOP.

Contributed by STMicroelectronics

Change-Id: I64722b17138582a76bb9cf604a6b0c14685f1720
Signed-off-by: Torbjörn Svensson <torbjorn.svensson@st.com>
This commit is contained in:
Torbjörn SVENSSON 2021-10-18 16:53:24 +02:00 committed by Torbjörn Svensson
parent cd73469b01
commit 4a7bd0d1b4

View file

@ -66,12 +66,17 @@ public class Spawner extends Process {
int pid = 0;
int status;
final IChannel[] fChannels = { null, null, null };
boolean isDone;
OutputStream out;
InputStream in;
InputStream err;
private PTY fPty;
private static enum State {
RUNNING, DESTROYING, DONE
}
private State fState = State.RUNNING;
/**
* @deprecated Do not use this method it splits command line arguments on whitespace with no regard to quoting rules. See Bug 573677
*/
@ -223,7 +228,7 @@ public class Spawner extends Process {
**/
@Override
public synchronized int waitFor() throws InterruptedException {
while (!isDone) {
while (fState != State.DONE) {
wait();
}
@ -245,7 +250,7 @@ public class Spawner extends Process {
**/
@Override
public synchronized int exitValue() {
if (!isDone) {
if (fState != State.DONE) {
throw new IllegalThreadStateException("Process not Terminated"); //$NON-NLS-1$
}
return status;
@ -260,6 +265,10 @@ public class Spawner extends Process {
**/
@Override
public synchronized void destroy() {
switch (fState) {
case RUNNING:
fState = State.DESTROYING;
// Sends the TERM
terminate();
@ -284,16 +293,23 @@ public class Spawner extends Process {
// But 345164
closeUnusedStreams();
// Grace before using the heavy gone.
if (!isDone) {
// Grace before using the heavy gun.
if (fState != State.DONE) {
try {
wait(1000);
} catch (InterruptedException e) {
}
}
if (!isDone) {
if (fState != State.DONE) {
kill();
}
break;
case DESTROYING:
case DONE:
// Nothing to do
break;
}
}
@Override
@ -563,7 +579,7 @@ public class Spawner extends Process {
// Sync with spawner and notify when done.
status = waitFor(pid);
synchronized (Spawner.this) {
isDone = true;
fState = Spawner.State.DONE;
Spawner.this.notifyAll();
}
}