More problems with boost::asio and async_read
Hi
I posted on this a couple of hours ago with some problems. It turned
out that some of the problems I had might have been due to buggy
hardware.
But there is still some thing I do not understand...
So, now I have reproduced some of of the problems I have with out any
hardware (except from a PC).
Basically I'm trying to read from a input source (in this case stdin)
with a timeout. Due to the design of the existing application where
this have to fit is it not possible to call run on my io_service.
Here is my try so far:
#include ::_M_deallocate(char*, unsigned long) (stl_vector.h:146)
==17848== by 0x42FD64: std::_Vector_base in> timeout
3 Type in 4 chareters and press enter
in> timeout
4 Type in 4 chareters and press enter
in> timeout
==17848==
==17848== HEAP SUMMARY:
==17848== in use at exit: 168 bytes in 3 blocks
==17848== total heap usage: 65 allocs, 62 frees, 22,246 bytes allocated
==17848==
==17848== LEAK SUMMARY:
==17848== definitely lost: 0 bytes in 0 blocks
==17848== indirectly lost: 0 bytes in 0 blocks
==17848== possibly lost: 0 bytes in 0 blocks
==17848== still reachable: 168 bytes in 3 blocks
==17848== suppressed: 0 bytes in 0 blocks
==17848== Rerun with --leak-check=full to see details of leaked memory
==17848==
==17848== For counts of detected and suppressed errors, rerun with: -v
==17848== Use --track-origins=yes to see where uninitialised values come from
==17848== ERROR SUMMARY: 27 errors from 9 contexts (suppressed: 4 from 4)
I have tried different things to fix, but I that I might have mis
understood a thing or two here. So some help would be most
appreciated.
--
Allan W. Nielsen
Basically I'm trying to read from a input source (in this case stdin) with a timeout. Due to the design of the existing application where this have to fit is it not possible to call run on my io_service.
Here is my try so far:
#include
#include #include using namespace std;
void set_result( boost::optionalboost::system::error_code * a, boost::system::error_code b ) { if( b == 0) a->reset( b ); }
void receive(boost::asio::io_service & io, boost::asio::posix::stream_descriptor & stream, boost::asio::streambuf & result){ boost::optionalboost::system::error_code timer_result; boost::optionalboost::system::error_code read_result;
boost::asio::deadline_timer timer( io ); timer.expires_from_now( boost::posix_time::milliseconds(5000) ); // allow up to 50ms of timeout for every char timer.async_wait( boost::bind(&set_result, &timer_result, _1) );
boost::asio::async_read( stream, result, boost::asio::transfer_at_least(1), boost::bind( &set_result, &read_result, _1 )); boost::system::error_code ec;
while(1) { io.reset(); io.poll_one(ec);
if ( read_result ) { timer.cancel(); return;
} else if ( timer_result ) throw std::runtime_error("timeout"); } }
void receive(boost::asio::io_service & io, boost::asio::posix::stream_descriptor & stream, size_t size, boost::asio::streambuf & result){ while( result.size() < size ) receive(io, stream, result); }
int main(int argc, const char *argv[]) { boost::asio::io_service io; boost::asio::posix::stream_descriptor in(io, ::dup(STDIN_FILENO));
for(int i = 0; i < 5; i++){ std::cout << i << " Type in 4 chareters and press enter" << std::endl << std::endl; std::cout << "in> "; std::cout.flush(); try { boost::asio::streambuf buf; receive(io, in, 5, buf); std::cout << "out> "; std::copy(boost::asio::buffer_cast
(buf.data()), boost::asio::buffer_cast (buf.data()) + buf.size(), ostream_iterator<char>(std::cout)); } catch (const std::exception & e) { std::cout << e.what() << endl; } }
return 0; }
You bind your completion handlers to addresses of local objects. I admit I didn't investigate your code in depth, but at a glance - I'm not sure all these locals always outlive the appropriate functors...
Hi
You bind your completion handlers to addresses of local objects. I admit I didn't investigate your code in depth, but at a glance - I'm not sure all these locals always outlive the appropriate functors...
Well, that is also what I think, but how am I suppose to cancel the async_read such that it will not interrupt me later on or??
It's asynchronous function, and it's completion handler will be called whether the operation is completed or cancelled.
Yes, but how do I tell the async_read that it is cancelled? It is just a free function which returns no handle or anything?? Should I let the boost::asio::posix::stream_descriptor object go out of scope to clean up all the references? -- Allan
Hi Again
I have now adjusted it to not take references to any temporary objects:
#include (buf.data()), boost::asio::buffer_cast return s;
}
private:
boost::asio::io_service io_service;
boost::asio::posix::stream_descriptor io_stream;
boost::asio::streambuf buf;
boost::optionalboost::system::error_code timer_result;
boost::optionalboost::system::error_code read_result;
};
int main(int argc, const char *argv[]) {
ReadWithTimeout xx;
for(int i = 0; i < 5; i++){
std::cout << i << " Type in 4 chareters and press enter" <<
std::endl << std::endl;
std::cout << "in> ";
std::cout.flush();
try {
std::cout << "out> " << xx.receive(5);
} catch (const std::exception & e) {
std::cout << e.what() << std::endl;
}
}
return 0;
}
But, I'm not sure whether this is a good idea, because I keep on
creating new async_read (things, objects??) how are they being cleaned
up?
--
Allan
But, I'm not sure whether this is a good idea, because I keep on creating new async_read (things, objects??) how are they being cleaned up?
async_read() is just a free function call. One of its parameters is a completion handler, which you create using bind(). This completion hanlder is put to some internal queue managed by io_service, and when the operation is successfully completed or failed or cancelled, the io_serivce cares to invoke the associated completion handler (for this purpose you have pump io_sevice queue with poll or run methods). After the handler is invoked, it's destroyed. So you don't have to "clean-up" anything here, but you do have to ensure that everything you bind into a handler remains alive until the handler gets invoked.
Yes, but how do I tell the async_read that it is cancelled?
It is just a free function which returns no handle or anything??
Should I let the boost::asio::posix::stream_descriptor object go out of scope to clean up all the references?
Calling cancel() on the i/o object cancels all async. operations associated with it: http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/posix__ba...
Just for the record, I finally found the problem. The async_read operation needs to be canceled just like the timer: while(1) { io.reset(); io.poll_one(ec); if ( read_result ) { timer.cancel(); return; } else if ( timer_result ) { stream.cancel(); throw std::runtime_error("timeout"); } } } -- Allan
participants (2)
-
Allan Nielsen
-
Igor R