Skip to content

Commit b95aa4c

Browse files
Fix bugs in Semaphore::timedWait (#292)
* Fix `timedWait` not differentiating error types Previously it would always return `kFail`, so the caller could not differentiate timeouts from real errors. Also it did not retry on `EINTR`. * Fix `timedWait` accumulating errors --------- Co-authored-by: Nicolas Fußberger <145956508+NicolasFussberger@users.noreply.github.com>
1 parent 0a69424 commit b95aa4c

1 file changed

Lines changed: 26 additions & 18 deletions

File tree

  • score/launch_manager/src/daemon/src/osal/details/posix

score/launch_manager/src/daemon/src/osal/details/posix/semaphore.cpp

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,27 +49,35 @@ OsalReturnType Semaphore::deinit() {
4949
OsalReturnType Semaphore::timedWait(std::chrono::milliseconds delay) {
5050
// Cannot use sem_timedwait because it relies on the absolute time of
5151
// the system clock, which is not monotonic and could be changed
52-
// by another thread. To minimise busy time and reduce accumulated
53-
// timing error on long delays, the resolution of the timer is set
54-
// at two milliseconds
55-
OsalReturnType result = OsalReturnType::kFail;
56-
std::chrono::milliseconds resolution = std::chrono::milliseconds(2U);
57-
bool wait = true;
58-
while (wait) {
59-
errno = 0;
60-
if (sem_trywait(&sem_) != 0) {
61-
if ((EAGAIN == errno) && (delay >= resolution)) {
52+
// by another thread.
53+
54+
// To minimise busy time, the resolution of the timer is set at 2 ms.
55+
const auto resolution = std::chrono::milliseconds(2U);
56+
57+
// Calculate when the timeout will be reached. This avoids accumulating
58+
// errors because `sleep_for` may block for longer than requested.
59+
const auto deadline = std::chrono::steady_clock::now() + delay;
60+
61+
while (true)
62+
{
63+
if (sem_trywait(&sem_) == 0)
64+
return OsalReturnType::kSuccess;
65+
66+
switch (errno) {
67+
case (EINTR):
68+
continue;
69+
70+
case (EAGAIN):
71+
if (std::chrono::steady_clock::now() >= deadline)
72+
return OsalReturnType::kTimeout;
73+
6274
std::this_thread::sleep_for(resolution);
63-
delay = delay - resolution;
64-
} else {
65-
wait = false;
66-
}
67-
} else {
68-
wait = false;
69-
result = OsalReturnType::kSuccess;
75+
continue;
76+
77+
default:
78+
return osal::OsalReturnType::kFail;
7079
}
7180
};
72-
return result;
7381
}
7482

7583
OsalReturnType Semaphore::post() {

0 commit comments

Comments
 (0)