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:
parent
cd73469b01
commit
4a7bd0d1b4
1 changed files with 50 additions and 34 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue