From 6e5f3d432e8296c750bbd2e982f65ac543db1be0 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Fri, 10 Feb 2017 23:21:59 +0100 Subject: [PATCH] Post signal-handler hook in entrypoint A Signal_handler may schedule a hook function that is executed after the signal handler returned. This can be used if the hook function may trigger a (nested) signal handler by means of wait_and_dispatch_one_signal(). Otherwise, an occurrence of the same signal that triggered the original signal handler results in a dead lock just before calling the nested handler (due to the Signal_context destruction lock). --- repos/base/include/base/entrypoint.h | 35 ++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/repos/base/include/base/entrypoint.h b/repos/base/include/base/entrypoint.h index 8318dabb9c..2c47f08451 100644 --- a/repos/base/include/base/entrypoint.h +++ b/repos/base/include/base/entrypoint.h @@ -30,6 +30,13 @@ namespace Genode { class Genode::Entrypoint : Genode::Noncopyable { + public: + + /** + * Functor for post signal-handler hook + */ + struct Post_signal_hook { virtual void function() = 0; }; + private: struct Signal_proxy @@ -46,10 +53,13 @@ class Genode::Entrypoint : Genode::Noncopyable void signal() { + /* XXX introduce while-pending loop */ try { Signal sig = ep._sig_rec->pending_signal(); ep._dispatch_signal(sig); } catch (Signal_receiver::Signal_not_pending) { } + + ep._execute_post_signal_hook(); } }; @@ -79,6 +89,16 @@ class Genode::Entrypoint : Genode::Noncopyable void (*_suspended_callback) () = nullptr; void (*_resumed_callback) () = nullptr; + Post_signal_hook *_post_signal_hook = nullptr; + + void _execute_post_signal_hook() + { + if (_post_signal_hook != nullptr) + _post_signal_hook->function(); + + _post_signal_hook = nullptr; + } + /* * This signal handler is solely used to force an iteration of the * signal-dispatch loop. It is triggered by 'schedule_suspend' to @@ -146,8 +166,11 @@ class Genode::Entrypoint : Genode::Noncopyable */ void wait_and_dispatch_one_signal() { - Signal sig = _sig_rec->wait_for_signal(); - _dispatch_signal(sig); + { + Signal sig = _sig_rec->wait_for_signal(); + _dispatch_signal(sig); + } + _execute_post_signal_hook(); } /** @@ -162,6 +185,14 @@ class Genode::Entrypoint : Genode::Noncopyable * state, while 'resumed is called when the entrypoint is fully functional again. */ void schedule_suspend(void (*suspended)(), void (*resumed)()); + + /** + * Register hook functor to be called after signal was handled + */ + void schedule_post_signal_hook(Post_signal_hook *hook) + { + _post_signal_hook = hook; + } }; #endif /* _INCLUDE__BASE__ENTRYPOINT_H_ */