[asio] strange behaviour on android
Hello, Recently I ported my application to Android, and after some testing I encountered the following strange behavior. Long story short: I send text to a peer and sometimes it gets "cut" in the beginning. like this: aaa\r\nbbb\r\nccc\r\nddd\r\n becomes \nccc\r\nddd\r\n I checked with sniffer, and ensured that the problem is really in my application. To send the text I use the following simple approach: * io_service::run is always invoked from one thread * the data comes from another thread and gets posted to the io_service thread: void connection::send(const std::string &str) { io_.post(boost::bind(&connection::doSend, shared_from_this(), str)); } * then it's streamed into asio::streambuf: void connection::doSend(const std::string &str) { std::ostream(&output_).write(str.c_str(), str.length()); } * and finally async_write is invoked, IF it's not in progress: if (!activeWrite_) { activeWrite_ = true; async_write(m_output, boost::bind(&connection::sent, shared_from_this(), asio::placeholders::error)); } (of course, in sent() handler async_write is re-activated, if needed). I understand that I add data to the streambuf, while async_write is in progress, but it's done in the same thread, and seems to be legitimate. The above approach works on Windows and on some other platforms, it was stress-tested, and never showed any problem. OTOH, on Android the above issue happens very frequently (~20% of events). The only difference here is that I compiled my project with BOOST_ASIO_DISABLE_FENCED_BLOCK, because otherwise the linker complains it doesn't see definitions of some gcc synchronization intrinsics. Is it possible that this's the problem? As far as I see, fenced_block is used when a completion handler is called, so I can't see how it can be connected to my problem... Anyway, I'd appreciate any idea. Thanks.
I understand that I add data to the streambuf, while async_write is in progress, but it's done in the same thread, and seems to be legitimate.
Well, after a more close look at the implementation of streambuf, I realized that this was absolutely invalid approach. When async_write() gets streamuf, its data() (actually a pointer to an element of std::vector) is passed to the underlying implementation.
From this point, any additional data put into the streambuf, might cause a resizing of the underlying std::vector, and such a resize invalidates the ptr previously returned from data(). I really don't understand why it never fails on Windows. Maybe just because WSASend works very quickly :).
participants (1)
-
Igor R