[Boost-users] [Asio] run_one does not seem to run signal handler but run does

79 views
Skip to first unread message

Robert Valkenburg

unread,
Feb 28, 2015, 9:39:16 PM2/28/15
to boost...@lists.boost.org
Hi,

I am reasonably new to Boost.Asio. Below is a short test program to
catch CNTR C. It nearly works as i would have expected.

#include <iostream>

#include <boost/version.hpp>
#define BOOST_ASIO_ENABLE_HANDLER_TRACKING
#include <boost/asio.hpp>

namespace asio = boost::asio;

#define GCC_VERSION (__GNUC__*10000 + __GNUC_MINOR__*100 +
__GNUC_PATCHLEVEL__ )

struct Sig_handler {

Sig_handler(int& count, asio::signal_set& signals) : count_(count),
signals_(signals) {}

void operator()(const boost::system::error_code& ec, int signal_number) {
if (!ec) {
count_++;
std::cout << "signal: " << signal_number << std::endl;
if (count_ < 3)
signals_.async_wait( Sig_handler(count_, signals_));
}
else {
std::cout << "Sig_handler error" << std::endl;
}
}

int& count_;
asio::signal_set& signals_;
};


int main()
{
std::cout << "test_asio_sig starting " << std::endl;
std::cout << "GCC VERSION " << GCC_VERSION << std::endl;
std::cout << "BOOST VERSION " << BOOST_VERSION << std::endl;

asio::io_service io_service;
asio::signal_set signals(io_service, SIGINT);

int count = 0;
std::cout << "count " << count << std::endl;

signals.async_wait( Sig_handler(count, signals) );

size_t num_handlers = io_service.run();
// size_t num_handlers = io_service.run_one(); // <<== NOTE

std::cout << "num handlers " << num_handlers << std::endl;
std::cout << "count " << count << std::endl;
std::cout << "test_asio_sig finishing " << std::endl;
}


Here is the output after pressing CNTR C 3 times

[robert@localhost misc]$ ./test_asio_sig
test_asio_sig starting
GCC VERSION 40902
BOOST VERSION 105700
count 0
@asio|1425176527.462503|0*1|signa...@0x7fffcd9139b8.async_wait
^C@asio|1425176530.453067|>1|ec=system:0,signal_number=2
signal: 2
@asio|1425176530.453092|1*2|signa...@0x7fffcd9139b8.async_wait
@asio|1425176530.453102|<1|
^C@asio|1425176533.749159|>2|ec=system:0,signal_number=2
signal: 2
@asio|1425176533.749187|2*3|signa...@0x7fffcd9139b8.async_wait
@asio|1425176533.749191|<2|
^C@asio|1425176548.261061|>3|ec=system:0,signal_number=2
signal: 2
@asio|1425176548.261092|<3|
num handlers 6
count 3
test_asio_sig finishing
@asio|1425176548.261116|0|signa...@0x7fffcd9139b8.cancel
[robert@localhost misc]$

I don't understand why io_service.run() says 6 handlers where invoked
but otherwise it seems OK.

Now if i replace io_service.run() with io_service.run_one() i
expected the handler to be invoked once when CNTR C is pressed. Here
is the output

[robert@localhost misc]$ ./test_asio_sig
test_asio_sig starting
GCC VERSION 40902
BOOST VERSION 105700
count 0
@asio|1425176928.548934|0*1|signa...@0x7fffe64b8398.async_wait
^Cnum handlers 1
count 0
test_asio_sig finishing
@asio|1425176930.187377|0|signa...@0x7fffe64b8398.cancel
@asio|1425176930.187411|~1|
[robert@localhost misc]$

This suggests one handler was invoked which is what i might have expected.
This does not have a line with >1 indicating entering the handler and
there is no output from the handler and count remains at 0.

Could someone help me to understand this.

[ I am using Fedora 21, gcc 4.9.2, x86_64, boost 1.57 ]


kind regards
_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Gavin Lambert

unread,
Mar 1, 2015, 5:29:41 PM3/1/15
to boost...@lists.boost.org
On 1/03/2015 15:39, Robert Valkenburg wrote:
> I don't understand why io_service.run() says 6 handlers where invoked
> but otherwise it seems OK.
>
> Now if i replace io_service.run() with io_service.run_one() i
> expected the handler to be invoked once when CNTR C is pressed. Here
> is the output
[...]
> This suggests one handler was invoked which is what i might have expected.
> This does not have a line with >1 indicating entering the handler and
> there is no output from the handler and count remains at 0.

"One handler" does not necessarily mean "one application code handler".
Many high-level async operations are actually composed internally of a
sequence of lower-level operations. As such, it may require multiple
internal handler calls before your user-level handler is actually called.

From your output, it appears that it your case it actually requires two
handler calls to actually invoke your application handler. However you
should not rely on this as it may change if the internals of Asio change
or if some other condition in your execution environment changes.

run_one() is intended to be called in a loop with other "idle" work --
but using run() is preferred whenever you can just post the extra work
to the io_service anyway.

Note that an async_wait is a single-shot thing anyway -- if you didn't
call async_wait again in your handler then it would only catch the
signal once, if that's what you're trying to do.

Robert Valkenburg

unread,
Mar 2, 2015, 2:30:50 AM3/2/15
to boost...@lists.boost.org
Thanks for the clarification,

On Mon, Mar 2, 2015 at 11:29 AM, Gavin Lambert <gav...@compacsort.com> wrote:
>
> "One handler" does not necessarily mean "one application code handler".
> Many high-level async operations are actually composed internally of a
> sequence of lower-level operations. As such, it may require multiple
> internal handler calls before your user-level handler is actually called.
>
> From your output, it appears that it your case it actually requires two
> handler calls to actually invoke your application handler. However you
> should not rely on this as it may change if the internals of Asio change or
> if some other condition in your execution environment changes.

Ok, so this explains the 6, and also explains the 1 for the run_one()
test (i.e. my handler did not get invoked). I added run_one() a
second time (with reset() in between) and my handler was invoked and
count equals 1 as expected .

>
> run_one() is intended to be called in a loop with other "idle" work -- but
> using run() is preferred whenever you can just post the extra work to the
> io_service anyway.

Ok, this is helpful.

>
> Note that an async_wait is a single-shot thing anyway -- if you didn't call
> async_wait again in your handler then it would only catch the signal once,
> if that's what you're trying to do.

Yes. This was only a small test program to help me understand ASIO
better. I was trying to use CTRL C was a mechanism to introduce a
console event (also looked at posix::stream_descriptor)
into the mix of socket (android) and serial port (arduino) events.

thanks again.
Reply all
Reply to author
Forward
0 new messages