diff options
author | Elena Sayapina <elena.v.sayapina@intel.com> | 2014-06-20 16:58:37 +0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2014-07-07 18:39:55 -0700 |
commit | 1af6a1fa35ff7dc0a5c653f19dbc8a91c914aa42 (patch) | |
tree | 07807547760383cfe9310c70ea00eace03b2740b /runtime/monitor.cc | |
parent | 13f89cb9930ea799c21559020da43c3845536da5 (diff) | |
download | art-1af6a1fa35ff7dc0a5c653f19dbc8a91c914aa42.tar.gz art-1af6a1fa35ff7dc0a5c653f19dbc8a91c914aa42.tar.bz2 art-1af6a1fa35ff7dc0a5c653f19dbc8a91c914aa42.zip |
ART: Update Monitor::Wait so it releases monitor_lock_ before throwing an exception
Thread should release monitor_lock_ Mutex (which guards shared structures behind Java monitor)
in Monitor::Wait before throwing any exception. Otherwise the thread may be suspended by GC
during that time still holding the lock. This may cause deadlock during GC in case
some other thread needs to acquire the monitor_lock_. The other thread can't be suspended
by GC then waiting for exclusive lock and "thread suspend timeout" occurs.
Change-Id: Id02f45052e1cfc01e676a43434125817564d7874
Signed-off-by: Elena Sayapina <elena.v.sayapina@intel.com>
Diffstat (limited to 'runtime/monitor.cc')
-rw-r--r-- | runtime/monitor.cc | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/runtime/monitor.cc b/runtime/monitor.cc index 999a9e504b..eb62a694e0 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -401,8 +401,8 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, // Make sure that we hold the lock. if (owner_ != self) { - ThrowIllegalMonitorStateExceptionF("object not locked by thread before wait()"); monitor_lock_.Unlock(self); + ThrowIllegalMonitorStateExceptionF("object not locked by thread before wait()"); return; } @@ -414,10 +414,10 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, // Enforce the timeout range. if (ms < 0 || ns < 0 || ns > 999999) { + monitor_lock_.Unlock(self); ThrowLocation throw_location = self->GetCurrentLocationForThrow(); self->ThrowNewExceptionF(throw_location, "Ljava/lang/IllegalArgumentException;", "timeout arguments out of range: ms=%" PRId64 " ns=%d", ms, ns); - monitor_lock_.Unlock(self); return; } @@ -512,6 +512,8 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, --num_waiters_; RemoveFromWaitSet(self); + monitor_lock_.Unlock(self); + if (was_interrupted) { /* * We were interrupted while waiting, or somebody interrupted an @@ -529,7 +531,6 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, self->ThrowNewException(throw_location, "Ljava/lang/InterruptedException;", NULL); } } - monitor_lock_.Unlock(self); } void Monitor::Notify(Thread* self) { |