[libgee/wip/issue/34] Guard GLib.Cond.wait/wait_until calls against spurious or stolen wakeups
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgee/wip/issue/34] Guard GLib.Cond.wait/wait_until calls against spurious or stolen wakeups
- Date: Sat, 5 Oct 2019 15:17:07 +0000 (UTC)
commit 35226d93e729bb98825eea4ab388c4045b838834
Author: Rico Tzschichholz <ricotz ubuntu com>
Date: Sat Oct 5 17:12:25 2019 +0200
Guard GLib.Cond.wait/wait_until calls against spurious or stolen wakeups
It is possible that a spurious or stolen wakeup could occur. For that
reason, waiting on a condition variable should always be in a loop,
based on an explicitly-checked predicate.
Fixes https://gitlab.gnome.org/GNOME/libgee/issues/34
gee/lazy.vala | 16 ++++++++++------
gee/promise.vala | 20 ++++++++++++--------
2 files changed, 22 insertions(+), 14 deletions(-)
---
diff --git a/gee/lazy.vala b/gee/lazy.vala
index 5e7bc36..4e09e8b 100644
--- a/gee/lazy.vala
+++ b/gee/lazy.vala
@@ -93,7 +93,9 @@ public class Gee.Lazy<G> {
_mutex.lock ();
if (_lazy._func != null) {
if (_state == State.EVAL) {
- _eval.wait (_mutex);
+ while (_state == State.EVAL) {
+ _eval.wait (_mutex);
+ }
_mutex.unlock ();
} else {
do_eval ();
@@ -108,12 +110,14 @@ public class Gee.Lazy<G> {
_mutex.lock ();
if (_lazy._func != null) {
if (_state == State.EVAL) {
- bool res = _eval.wait_until (_mutex, end_time);
- _mutex.unlock ();
- if (!res) {
- value = null;
- return false;
+ while (_state == State.EVAL) {
+ if (!_eval.wait_until (_mutex, end_time)) {
+ value = null;
+ _mutex.unlock ();
+ return false;
+ }
}
+ _mutex.unlock ();
} else {
do_eval ();
}
diff --git a/gee/promise.vala b/gee/promise.vala
index 401014d..020138e 100644
--- a/gee/promise.vala
+++ b/gee/promise.vala
@@ -93,10 +93,11 @@ public class Gee.Promise<G> {
_mutex.lock ();
State state = _state;
if (_state == State.INIT) {
- _set.wait (_mutex);
- state = _state;
+ while (_state == State.INIT) {
+ _set.wait (_mutex);
+ state = _state;
+ }
}
- assert (state != State.INIT);
_mutex.unlock ();
switch (state) {
case State.ABANDON:
@@ -114,14 +115,17 @@ public class Gee.Promise<G> {
_mutex.lock ();
State state = _state;
if (state == State.INIT) {
- _set.wait_until (_mutex, end_time);
- state = _state;
+ while (_state == State.INIT) {
+ if (!_set.wait_until (_mutex, end_time)) {
+ value = null;
+ _mutex.unlock ();
+ return false;
+ }
+ state = _state;
+ }
}
_mutex.unlock ();
switch (state) {
- case State.INIT:
- value = null;
- return false;
case State.ABANDON:
throw new FutureError.ABANDON_PROMISE ("Promise has been abandon");
case State.EXCEPTION:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]