mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
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:
parent
44f7bd9fe0
commit
8d2ca7aaf5
@ -306,11 +306,9 @@ class MySystem: public System {
|
||||
|
||||
{ ACQUIRE(t->mutex);
|
||||
|
||||
if (t->r->interrupted()) {
|
||||
if (clearInterrupted) {
|
||||
t->r->setInterrupted(false);
|
||||
}
|
||||
return true;
|
||||
interrupted = t->r->interrupted();
|
||||
if (interrupted and clearInterrupted) {
|
||||
t->r->setInterrupted(false);
|
||||
}
|
||||
|
||||
t->flags |= Waiting;
|
||||
@ -322,27 +320,29 @@ class MySystem: public System {
|
||||
owner_ = 0;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
// pretend anything greater than one million years (in
|
||||
// milliseconds) is infinity so as to avoid overflow:
|
||||
if (time and time < INT64_C(31536000000000000)) {
|
||||
int64_t then = s->now() + time;
|
||||
timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 };
|
||||
int rv UNUSED = pthread_cond_timedwait
|
||||
(&(t->condition), &(t->mutex), &ts);
|
||||
expect(s, rv == 0 or rv == ETIMEDOUT or rv == EINTR);
|
||||
} else {
|
||||
int rv UNUSED = pthread_cond_wait(&(t->condition), &(t->mutex));
|
||||
expect(s, rv == 0 or rv == EINTR);
|
||||
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)) {
|
||||
int64_t then = s->now() + time;
|
||||
timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 };
|
||||
int rv UNUSED = pthread_cond_timedwait
|
||||
(&(t->condition), &(t->mutex), &ts);
|
||||
expect(s, rv == 0 or rv == ETIMEDOUT or rv == EINTR);
|
||||
} else {
|
||||
int rv UNUSED = pthread_cond_wait(&(t->condition), &(t->mutex));
|
||||
expect(s, rv == 0 or rv == EINTR);
|
||||
}
|
||||
|
||||
interrupted = t->r->interrupted();
|
||||
if (interrupted and clearInterrupted) {
|
||||
t->r->setInterrupted(false);
|
||||
}
|
||||
}
|
||||
|
||||
notified = ((t->flags & Notified) != 0);
|
||||
|
||||
t->flags = 0;
|
||||
|
||||
interrupted = t->r->interrupted();
|
||||
if (interrupted and clearInterrupted) {
|
||||
t->r->setInterrupted(false);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
@ -269,12 +269,10 @@ class MySystem: public System {
|
||||
int r UNUSED;
|
||||
|
||||
{ ACQUIRE(s, t->mutex);
|
||||
|
||||
if (t->r->interrupted()) {
|
||||
if (clearInterrupted) {
|
||||
t->r->setInterrupted(false);
|
||||
}
|
||||
return true;
|
||||
|
||||
interrupted = t->r->interrupted();
|
||||
if (interrupted and clearInterrupted) {
|
||||
t->r->setInterrupted(false);
|
||||
}
|
||||
|
||||
t->flags |= Waiting;
|
||||
@ -288,26 +286,28 @@ class MySystem: public System {
|
||||
bool success UNUSED = ReleaseMutex(mutex);
|
||||
assert(s, success);
|
||||
|
||||
success = ResetEvent(t->event);
|
||||
assert(s, success);
|
||||
if (not interrupted) {
|
||||
success = ResetEvent(t->event);
|
||||
assert(s, success);
|
||||
|
||||
success = ReleaseMutex(t->mutex);
|
||||
assert(s, success);
|
||||
success = ReleaseMutex(t->mutex);
|
||||
assert(s, success);
|
||||
|
||||
r = WaitForSingleObject(t->event, (time ? time : INFINITE));
|
||||
assert(s, r == WAIT_OBJECT_0 or r == WAIT_TIMEOUT);
|
||||
r = WaitForSingleObject(t->event, (time ? time : INFINITE));
|
||||
assert(s, r == WAIT_OBJECT_0 or r == WAIT_TIMEOUT);
|
||||
|
||||
r = WaitForSingleObject(t->mutex, INFINITE);
|
||||
assert(s, r == WAIT_OBJECT_0);
|
||||
r = WaitForSingleObject(t->mutex, INFINITE);
|
||||
assert(s, r == WAIT_OBJECT_0);
|
||||
|
||||
interrupted = t->r->interrupted();
|
||||
if (interrupted and clearInterrupted) {
|
||||
t->r->setInterrupted(false);
|
||||
}
|
||||
}
|
||||
|
||||
notified = ((t->flags & Notified) != 0);
|
||||
|
||||
t->flags = 0;
|
||||
|
||||
interrupted = t->r->interrupted();
|
||||
if (interrupted and clearInterrupted) {
|
||||
t->r->setInterrupted(false);
|
||||
}
|
||||
}
|
||||
|
||||
r = WaitForSingleObject(mutex, INFINITE);
|
||||
|
Loading…
Reference in New Issue
Block a user