From 7386c4e1d1bebcedc4b76b965dbe7621c3dd2893 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Fri, 16 Dec 2016 21:08:00 +0100 Subject: [PATCH] More robust handling of suspend in entrypoint First, calls to manage and dissolve signal contexts now check if the signal receiver was constructed. There is a small window during suspend where it is destructed before reconstructed again. Last, we ensure that processing of incoming signal was deblocked by the suspend signal before entering the suspend operation. This way we ensure already queued signal are handled. --- repos/base/include/base/entrypoint.h | 3 ++- repos/base/src/lib/base/entrypoint.cc | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/repos/base/include/base/entrypoint.h b/repos/base/include/base/entrypoint.h index 87d485fa8c..8318dabb9c 100644 --- a/repos/base/include/base/entrypoint.h +++ b/repos/base/include/base/entrypoint.h @@ -75,6 +75,7 @@ class Genode::Entrypoint : Genode::Noncopyable Reconstructible _sig_rec; + bool _suspended = false; void (*_suspended_callback) () = nullptr; void (*_resumed_callback) () = nullptr; @@ -84,7 +85,7 @@ class Genode::Entrypoint : Genode::Noncopyable * let the signal-dispatching thread execute the actual suspend- * resume mechanism. */ - void _handle_suspend() { } + void _handle_suspend() { _suspended = true; } Constructible> _suspend_dispatcher; void _dispatch_signal(Signal &sig); diff --git a/repos/base/src/lib/base/entrypoint.cc b/repos/base/src/lib/base/entrypoint.cc index 946854f3a3..b84dce1e6e 100644 --- a/repos/base/src/lib/base/entrypoint.cc +++ b/repos/base/src/lib/base/entrypoint.cc @@ -74,7 +74,7 @@ void Entrypoint::_process_incoming_signals() [] () { warning("blocking canceled during signal processing"); } ); - } while (!_suspended_callback); + } while (!_suspended); _suspend_dispatcher.destruct(); _sig_rec.destruct(); @@ -100,6 +100,7 @@ void Entrypoint::_process_incoming_signals() void (*resumed_callback)() = _resumed_callback; _suspended_callback = nullptr; _resumed_callback = nullptr; + _suspended = false; resumed_callback(); } @@ -124,13 +125,17 @@ void Entrypoint::schedule_suspend(void (*suspended)(), void (*resumed)()) Signal_context_capability Entrypoint::manage(Signal_dispatcher_base &dispatcher) { - return _sig_rec->manage(&dispatcher); + /* _sig_rec is invalid for a small window in _process_incoming_signals */ + return _sig_rec.constructed() ? _sig_rec->manage(&dispatcher) + : Signal_context_capability(); } void Genode::Entrypoint::dissolve(Signal_dispatcher_base &dispatcher) { - _sig_rec->dissolve(&dispatcher); + /* _sig_rec is invalid for a small window in _process_incoming_signals */ + if (_sig_rec.constructed()) + _sig_rec->dissolve(&dispatcher); }