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