fix Thread.interrupt deadlock

Previously, we returned immediately from Monitor.wait if we found we
had been interrupted, but this caused deadlock when waiting to enter
the exclusive state, since we never released Machine::stateLock to
allow active threads to transition into the idle state.  This commit
ensures that we at least briefly release the lock without actually
waiting in that case.
This commit is contained in:
Joel Dice 2011-08-11 07:35:03 -06:00
parent 44f7bd9fe0
commit 8d2ca7aaf5
2 changed files with 40 additions and 40 deletions

View File

@ -306,12 +306,10 @@ class MySystem: public System {
{ ACQUIRE(t->mutex);
if (t->r->interrupted()) {
if (clearInterrupted) {
interrupted = t->r->interrupted();
if (interrupted and clearInterrupted) {
t->r->setInterrupted(false);
}
return true;
}
t->flags |= Waiting;
@ -322,6 +320,7 @@ class MySystem: public System {
owner_ = 0;
pthread_mutex_unlock(&mutex);
if (not interrupted) {
// pretend anything greater than one million years (in
// milliseconds) is infinity so as to avoid overflow:
if (time and time < INT64_C(31536000000000000)) {
@ -335,16 +334,17 @@ class MySystem: public System {
expect(s, rv == 0 or rv == EINTR);
}
notified = ((t->flags & Notified) != 0);
t->flags = 0;
interrupted = t->r->interrupted();
if (interrupted and clearInterrupted) {
t->r->setInterrupted(false);
}
}
notified = ((t->flags & Notified) != 0);
t->flags = 0;
}
pthread_mutex_lock(&mutex);
if (not notified) {

View File

@ -270,12 +270,10 @@ class MySystem: public System {
{ ACQUIRE(s, t->mutex);
if (t->r->interrupted()) {
if (clearInterrupted) {
interrupted = t->r->interrupted();
if (interrupted and clearInterrupted) {
t->r->setInterrupted(false);
}
return true;
}
t->flags |= Waiting;
@ -288,6 +286,7 @@ class MySystem: public System {
bool success UNUSED = ReleaseMutex(mutex);
assert(s, success);
if (not interrupted) {
success = ResetEvent(t->event);
assert(s, success);
@ -300,16 +299,17 @@ class MySystem: public System {
r = WaitForSingleObject(t->mutex, INFINITE);
assert(s, r == WAIT_OBJECT_0);
notified = ((t->flags & Notified) != 0);
t->flags = 0;
interrupted = t->r->interrupted();
if (interrupted and clearInterrupted) {
t->r->setInterrupted(false);
}
}
notified = ((t->flags & Notified) != 0);
t->flags = 0;
}
r = WaitForSingleObject(mutex, INFINITE);
assert(s, r == WAIT_OBJECT_0);