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.
This commit is contained in:
Christian Helmuth 2016-12-16 21:08:00 +01:00 committed by Norman Feske
parent 9fffb004b2
commit 7386c4e1d1
2 changed files with 10 additions and 4 deletions

View File

@ -75,6 +75,7 @@ class Genode::Entrypoint : Genode::Noncopyable
Reconstructible<Signal_receiver> _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<Genode::Signal_handler<Entrypoint>> _suspend_dispatcher;
void _dispatch_signal(Signal &sig);

View File

@ -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);
}