{"action":"created","issue":{"url":"https://api.github.com/repos/reverbrain/swarm/issues/40","labels_url":"https://api.github.com/repos/reverbrain/swarm/issues/40/labels{/name}","comments_url":"https://api.github.com/repos/reverbrain/swarm/issues/40/comments","events_url":"https://api.github.com/repos/reverbrain/swarm/issues/40/events","html_url":"https://github.com/reverbrain/swarm/pull/40","id":67119466,"number":40,"title":"signal handling","user":{"login":"shindo","id":863752,"avatar_url":"https://avatars.githubusercontent.com/u/863752?v=3","gravatar_id":"","url":"https://api.github.com/users/shindo","html_url":"https://github.com/shindo","followers_url":"https://api.github.com/users/shindo/followers","following_url":"https://api.github.com/users/shindo/following{/other_user}","gists_url":"https://api.github.com/users/shindo/gists{/gist_id}","starred_url":"https://api.github.com/users/shindo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shindo/subscriptions","organizations_url":"https://api.github.com/users/shindo/orgs","repos_url":"https://api.github.com/users/shindo/repos","events_url":"https://api.github.com/users/shindo/events{/privacy}","received_events_url":"https://api.github.com/users/shindo/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":14,"created_at":"2015-04-08T12:34:19Z","updated_at":"2015-04-08T15:49:55Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/reverbrain/swarm/pulls/40","html_url":"https://github.com/reverbrain/swarm/pull/40","diff_url":"https://github.com/reverbrain/swarm/pull/40.diff","patch_url":"https://github.com/reverbrain/swarm/pull/40.patch"},"body":"OK, let's try again.\r\n\r\n----------------\r\nPublic Interface\r\n================\r\n\r\nOne can register custom handlers for specific signal with the following function:\r\n```(cpp)\r\nint ioremap::thevoid::register_signal_handler(int signal_number, signal_handler_type handler)\r\n```\r\n\r\nSignal handler's signature:\r\n```(cpp)\r\nvoid handler(int signal_number, base_server* server)\r\n```\r\n\r\nThis function returns 0 if registration was successful, and -1 otherwise.\r\n\r\nEach signal may be registered only once.\r\n\r\nWhen added signal is catched its associated handler will be invoked for each server within its separate thread (server's monitoring thread).\r\n\r\nFor each server, all registered signal handlers will be invoked from within single thread. But the same handler may be invoked concurrently for distinct servers.\r\n\r\nOne must not register their own signal handlers (with signal(), sigaction(), etc.) for added signals.\r\n\r\nThis function is thread-safe and may be called anytime.\r\n\r\n----------------\r\nImplementation\r\n==============\r\n\r\n- just before first signal's registration pipe will be opened. All received signals will be written to and can be read from the pipe (this is very close to what signalfd() does).\r\n\r\n- for each registered signal native handler is registered that just writes received signals to the pipe.\r\n\r\n- there's global set of \"subscribed\" servers with their io_services within which registered handlers will be invoked (each server's monitoring io_service is used for this task).\r\n\r\n- all registered servers are asynchronously reading the pipe (within their io_services), and once some server reads signal number from the pipe, it notifies all registered io_services with this signal's handler.\r\n\r\n- when server stops it deregisters itself from this global mechanics.\r\n\r\n-------------------\r\nExample (multiserver)\r\n===================\r\n\r\nmultiserver accepts multiple configuration files as program arguments and creates multiple servers according to passed configs:\r\n```(bash)\r\n./multiserver server-1.json server-2.json\r\n```\r\n\r\nEach server supports only /ping.\r\n    \r\nSignals handled with thevoid's mechanics:\r\n- SIGTERM, SIGINT signals stop servers\r\n- SIGHUP signal reloads servers' configuration\r\n- SIGUSR1, SIGUSR2 signals are ignored\r\n    \r\nAnd SIGALRM signal is handled \"manually\" (bypass thevoid's mechanics).\r\n\r\nThis example shows how one can use `register_signal_handler()` function to register their own handlers.\r\nMoreover, this example shows that one can register their own signal handlers with `sigaction()` (bypass thevoid's mechanics).\r\n\r\n----------------------\r\nSummary\r\n======================\r\nOne can register their own handlers within thevoid (handler will be called for each server within its separate monitoring thread that already exists).\r\n\r\nOne can register no handler within thevoid (just do not use `run_server()` and `register_signal_handler()`), and no signals will be handled by thevoid (even the pipe will not be created).\r\n\r\nOne can use standard methods to register signal handlers (`signal()`, `sigaction()`) for signals that are not registered with thevoid's `register_signal_handler()` function.\r\n\r\n`register_signal_handler()` may be called from any thread and anytime (**that's why we do not use `signalfd()`**, this solution is more complicated, but we do not limit user with unnecessary constraints)."},"comment":{"url":"https://api.github.com/repos/reverbrain/swarm/issues/comments/90957280","html_url":"https://github.com/reverbrain/swarm/pull/40#issuecomment-90957280","issue_url":"https://api.github.com/repos/reverbrain/swarm/issues/40","id":90957280,"user":{"login":"shindo","id":863752,"avatar_url":"https://avatars.githubusercontent.com/u/863752?v=3","gravatar_id":"","url":"https://api.github.com/users/shindo","html_url":"https://github.com/shindo","followers_url":"https://api.github.com/users/shindo/followers","following_url":"https://api.github.com/users/shindo/following{/other_user}","gists_url":"https://api.github.com/users/shindo/gists{/gist_id}","starred_url":"https://api.github.com/users/shindo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shindo/subscriptions","organizations_url":"https://api.github.com/users/shindo/orgs","repos_url":"https://api.github.com/users/shindo/repos","events_url":"https://api.github.com/users/shindo/events{/privacy}","received_events_url":"https://api.github.com/users/shindo/received_events","type":"User","site_admin":false},"created_at":"2015-04-08T15:49:55Z","updated_at":"2015-04-08T15:49:55Z","body":"Reworked with signalfd().\r\n\r\nSeparate thread (\"void_signal\") is used to monitor received signals.\r\n\r\nNow it's required to register all signal handlers before creating any threads.\r\nOne is not allowed to use `signal()`, `sigaction()`, etc. if they register signal handler with provided mechanics.\r\n\r\nOnce all handlers are registered one has to call `run_signal_thread()`.\r\nTo stop separate signal monitoring thread one has to call `stop_signal_thread()`."}}