Fix errno handling to avoid being overwritten
Bug: 124468627
Tested: m build-art-host
Change-Id: I4c9fba1ddd6374b8f4451b82ccfc7aed666c6ebc
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 4828aae..071c514 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -304,18 +304,27 @@
if (old_state == kNoPermit) {
// no permit was available. block thread until later.
Runtime::Current()->GetRuntimeCallbacks()->ThreadParkStart(is_absolute, time);
- int result = 0;
bool timed_out = false;
if (!is_absolute && time == 0) {
// Thread.getState() is documented to return waiting for untimed parks.
ScopedThreadSuspension sts(this, ThreadState::kWaiting);
DCHECK_EQ(NumberOfHeldMutexes(), 0u);
- result = futex(tls32_.park_state_.Address(),
+ int result = futex(tls32_.park_state_.Address(),
FUTEX_WAIT_PRIVATE,
/* sleep if val = */ kNoPermitWaiterWaiting,
/* timeout */ nullptr,
nullptr,
0);
+ // This errno check must happen before the scope is closed, to ensure that
+ // no destructors (such as ScopedThreadSuspension) overwrite errno.
+ if (result == -1) {
+ switch (errno) {
+ case EAGAIN:
+ FALLTHROUGH_INTENDED;
+ case EINTR: break; // park() is allowed to spuriously return
+ default: PLOG(FATAL) << "Failed to park";
+ }
+ }
} else if (time > 0) {
// Only actually suspend and futex_wait if we're going to wait for some
// positive amount of time - the kernel will reject negative times with
@@ -325,6 +334,7 @@
ScopedThreadSuspension sts(this, ThreadState::kTimedWaiting);
DCHECK_EQ(NumberOfHeldMutexes(), 0u);
timespec timespec;
+ int result = 0;
if (is_absolute) {
// Time is millis when scheduled for an absolute time
timespec.tv_nsec = (time % 1000) * 1000000;
@@ -350,15 +360,17 @@
nullptr,
0);
}
- }
- if (result == -1) {
- switch (errno) {
- case ETIMEDOUT:
- timed_out = true;
- FALLTHROUGH_INTENDED;
- case EAGAIN:
- case EINTR: break; // park() is allowed to spuriously return
- default: PLOG(FATAL) << "Failed to park";
+ // This errno check must happen before the scope is closed, to ensure that
+ // no destructors (such as ScopedThreadSuspension) overwrite errno.
+ if (result == -1) {
+ switch (errno) {
+ case ETIMEDOUT:
+ timed_out = true;
+ FALLTHROUGH_INTENDED;
+ case EAGAIN:
+ case EINTR: break; // park() is allowed to spuriously return
+ default: PLOG(FATAL) << "Failed to park";
+ }
}
}
// Mark as no longer waiting, and consume permit if there is one.