Regarding Daytime.3 - An asynchronous TCP daytime server: [1] There is no way to stop this server! I can kill it under Linux but then it aborts instead of exiting, which is in general not good. == My solution == Add a global quit event variable. Handle the QUIT signal by setting the quit event. Test for the quit event within the event loop. Thoughts? == References == [1] http://www.boost.org/doc/libs/1_42_0/doc/html/boost_asio/tutorial/tutdaytime...
Christopher Yeleighton
Regarding Daytime.3 - An asynchronous TCP daytime server: [1]
There is no way to stop this server! I can kill it under Linux but then it aborts instead of exiting, which is in general not good.
== My solution == Add a global quit event variable. Handle the QUIT signal by setting the quit event. Test for the quit event within the event loop.
Of course this works for the synchronous server where there is an explicit loop; an asynchronous server needs to call { service->stop(); } My experiment shows that it is does not produce any visible failure under SuSE; however, it is not clear whether io_service::stop can be called from within a signal handler. Help?
On Wed, 28 Apr 2010 16:23:43 +0200, Christopher Yeleighton
[...]Of course this works for the synchronous server where there is an explicit loop; an asynchronous server needs to call { service->stop(); } My experiment shows that it is does not produce any visible failure under SuSE; however, it is not clear whether io_service::stop can be called from within a signal handler.
It's not safe to call io_service::stop in a signal handler (io_service is thread-safe; there are Pthread functions called in io_service::stop which are not safe to call in signal handlers). Boris
Boris Schaeling
On Wed, 28 Apr 2010 16:23:43 +0200, Christopher Yeleighton
wrote: [...]Of course this works for the synchronous server where there is an explicit loop; an asynchronous server needs to call { service->stop(); } My experiment shows that it is does not produce any visible failure under SuSE; however, it is not clear whether io_service::stop can be called from within a signal handler.
It's not safe to call io_service::stop in a signal handler (io_service is thread-safe; there are Pthread functions called in io_service::stop which are not safe to call in signal handlers).
So how do I handle signals without breaking something? I applied this technique to the TCP echo server example [1]; the result is the active sessions are never destroyed (leaking) because they are destroyed in response to a network error only. Please help. The assumption that the server runs forever is unacceptable. Chris
On Wed, 28 Apr 2010 23:47:13 +0200, Christopher Yeleighton
[...]So how do I handle signals without breaking something?
You could for example create a pipe and write to it in the signal handler (write is a function you can call in a signal handler). Somewhere else in your program you read from the pipe (as you use Boost.Asio anyway eg. with boost::asio::posix::stream_descriptor). If read returns you know it's time to shutdown the server. And as you are not in a signal handler anymore you can call io_service::stop. Boris
Boris Schaeling
On Wed, 28 Apr 2010 23:47:13 +0200, Christopher Yeleighton
wrote: [...]So how do I handle signals without breaking something?
You could for example create a pipe and write to it in the signal handler (write is a function you can call in a signal handler). Somewhere else in
May I call socket::cancel in a signal handler? How do I dispose of the open session objects? Chris
On Thu, 29 Apr 2010 10:19:59 +0200, Christopher Yeleighton
[...]May I call socket::cancel in a signal handler? How do I dispose of the open session objects?
You may only call async-signal-safe functions in a signal handler (there is a list of those functions at http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html). As the documentation of Boost.Asio doesn't mention signal handlers (as far as I know), I wouldn't assume that it's safe to call any Boost.Asio function in a signal handler (this is only safe if the implementation of a Boost.Asio function only calls async-signal-safe functions; but then an implementation can change in a new version). Maybe you can propose (or create?) a stop function which is safe to call in a signal handler (sounds like a good contribution to Boost.Asio)? Boris
Boris Schaeling
implementation can change in a new version). Maybe you can propose (or create?) a stop function which is safe to call in a signal handler (sounds like a good contribution to Boost.Asio)?
Sure. The function would be void io_service::async_stop(void); /// Sets an internal flag in io_service to stop at the nearest event loop. /// May be called from a signal handler.
On Thu, 29 Apr 2010 15:13:04 +0200, Christopher Yeleighton
Boris Schaeling
writes: implementation can change in a new version). Maybe you can propose (or create?) a stop function which is safe to call in a signal handler (sounds like a good contribution to Boost.Asio)?
Sure. The function would be
void io_service::async_stop(void); /// Sets an internal flag in io_service to stop at the nearest event loop. /// May be called from a signal handler.
I suggest to submit your proposal at https://svn.boost.org/trac/boost/newticket. Boris
Boris Schaeling
I suggest to submit your proposal at https://svn.boost.org/trac/boost/newticket.
Christopher Yeleighton
May I call socket::cancel in a signal handler?
Rather acceptor::cancel; the idea is to cancel the listener in the signal handler. May I?
How do I dispose of the open session objects?
Calling io_session::stop does not cancel pending tasks, it just destroys them. Therefore all cleanup code should be in the destructor of the session object and thus the async TCP echo server example code is wrong. Session objects are not of value type because they contain a socket, which is a resource that cannot be copied. Therefore they cannot be passed by value. The reference to a session objects must be a value type; boost::shared_ptr is well suited for this task (std::auto_ptr is a resource type too). And indeed, the async TCP daytime server example does use boost::shared_ptr; why the async TCP echo server recourses to quirks like { if (error) delete this; } is beyond my understanding. The example is misleading and should be fixed. Chris
participants (2)
-
Boris Schaeling
-
Christopher Yeleighton