[Asio] async_read_until is passing no error and bytes_transferred of zero to handler
I wanted to ask on the mailing list about an issue I'm having with Boost.Asio on Windows 7 before making a bug report. System information: Windows 7 64-bit Professional running on an Intel quad-core i7 with 4 GB of RAM, using Visual Studio 2012 for C++ development. Used VS2012 compiler to compile Boost 1.55 libraries by following instructions found in the documentation online. In case it matters, here are the C++ preprocessor defines I'm using: WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;NOMINMAX;WIN32_LEAN_AND_MEAN; _WIN32_WINNT=0x0601; The project was compiled with the default debug settings for Visual Studio 2012, meaning no optimizations. The problem: While using Boost.Asio to communicate with a serial device (an Arduino, 250000 baud, 8n1), sometimes async_read_until would pass to the handler both a bytes_transferred of zero and an error condition indicating success. According to http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/ async_read_until/overload1.html, this should never occur (if I'm interpreting the documentation correctly). Specifically, under parameters, under handler: // The number of bytes in the streambuf's get // area up to and including the delimiter. // 0 if an error occurred. The odd thing about this problem is that it is not easily reproducible... I think it may be a race condition. The files I'm attaching include the wrapper class I made to access the serial port in Windows, with a small main function at the bottom of the implementation .cpp file. I almost couldn't reproduce the error with this setup-- it took me a few dozen runs to get it to manifest itself. I can guarantee that the problem does not lie with the Arduino or the UART communication-- I have been running USBPcap to make sure that USB communication is taking place. I can see all data travelling to and from the Arduino by analyzing the USBPcap output through Wireshark. The Arduino I have has a set of ASCII serial commands it supports. The only one I use in the included code is "?\r", which makes it return "ACK\r\nArduino\r\n". Based on my searching, the closest bugs to what I'm experiencing seem to be these ones: https://svn.boost.org/trac/boost/ticket/8933 https://svn.boost.org/trac/boost/ticket/8967 I considered disabling IOCP for testing, but serial port communication depends on IOCP in Windows. The original problem is far more reliably reproduced-- using Visual Studio's unit testing framework, I am running essentially the same code included in the main function of the included code. I'd say about one of every three or two runs results in the error using the unit testing framework. Running the code in the actual application I'm developing also reliably reproduces the problem (MFC application). The attached .zip file includes the stripped down version of the project used to reproduce the problem, the stack frame of the error as caught by the assert inside readUntilComplete, and a core dump with the heap for the stripped project when the error occurred. The debugging symbols for the core dump are also included in the top-most directory of the .zip file. I would greatly appreciate any input/suggestions on the issue. If people are having trouble reproducing the problem, I seemingly can occasionally reproduce it so I can do more analysis, if someone were to point me in the right direction. Thank you for your time! Sincerely, Gabriel E. Marcano
On 7 May 2014 at 18:00, Marcano, Gabriel E wrote:
Based on my searching, the closest bugs to what I'm experiencing seem to be these ones: https://svn.boost.org/trac/boost/ticket/8933 https://svn.boost.org/trac/boost/ticket/8967
Have you not tried applying the patches these issues provide and see what happens? Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
Based on my searching, the closest bugs to what I'm experiencing seem to be these ones: https://svn.boost.org/trac/boost/ticket/8933 https://svn.boost.org/trac/boost/ticket/8967
Have you not tried applying the patches these issues provide and see what happens?
I had not tried this earlier because I thought the patch proposed for ticket 8933 had been merged with the release branch. Upon checking, I noticed my assumption was incorrect. I patched my boost files and this did not solve my problem. I was hesitant to apply the patch from 8967 due to the discussion on that ticket (and it's invalid status), but I applied it now to test and it did not help either. I had to comment out a lot more on_pending calls that were not being commented out by the patch in order to get the patched code to compile. I can still reproduce the error. Gabriel -----Original Message----- From: Boost-users [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Niall Douglas Sent: Thursday, May 08, 2014 5:12 AM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [Asio] async_read_until is passing no error and bytes_transferred of zero to handler On 7 May 2014 at 18:00, Marcano, Gabriel E wrote:
Based on my searching, the closest bugs to what I'm experiencing seem to be these ones: https://svn.boost.org/trac/boost/ticket/8933 https://svn.boost.org/trac/boost/ticket/8967
Have you not tried applying the patches these issues provide and see what happens? Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
On 8 May 2014 at 14:21, Marcano, Gabriel E wrote:
Based on my searching, the closest bugs to what I'm experiencing seem to be these ones: https://svn.boost.org/trac/boost/ticket/8933 https://svn.boost.org/trac/boost/ticket/8967
Have you not tried applying the patches these issues provide and see what happens?
I had not tried this earlier because I thought the patch proposed for ticket 8933 had been merged with the release branch. Upon checking, I noticed my assumption was incorrect. I patched my boost files and this did not solve my problem. I was hesitant to apply the patch from 8967 due to the discussion on that ticket (and it's invalid status), but I applied it now to test and it did not help either. I had to comment out a lot more on_pending calls that were not being commented out by the patch in order to get the patched code to compile. I can still reproduce the error.
Arse. Ok, my last suggestion is to set num_threads=1 when constructing the io_service. Failing that, I am going to assume it is a bug in Windows. The serial port drivers in Windows have always been flaky, indeed downright broken from NT 3.5 up to Windows 2000. I'd search stackoverflow (e.g. https://stackoverflow.com/questions/12583482/serial-asynchronous-i-o-i n-windows-7-64) for serial port problems. Just because it may have worked on an older ASIO means little. Basically serial drivers on NT have always been brittle, you change one small thing and they stop working in weird ways. An boss of mine said "never use any serial API not used by HyperTerminal" and I think he was right. You might want to read the end of the page at http://www.codeproject.com/Articles/992/Serial-library-for-C too, *especially* the comments about trying to use a serial port handle from more than one thread. Despite that being in 2003, there is no reason to expect things have improved as I don't think serial port drivers get a lot of love from Microsoft. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
Ok, my last suggestion is to set num_threads=1 when constructing the io_service.
This worked for the first time I ran the tests... but the second time the problem resurfaced. What baffles me is that none of the other serial applications on my computer seem to be dropping bytes...
Just because it may have worked on an older ASIO means little.
I actually haven't tried any other version of ASIO with this code. It may or may not have worked before.
An boss of mine said "never use any serial API not used by HyperTerminal" and I think he was right.
I'm beginning to think this myself, and further, this could probably be generalized for a lot of more proprietary programming APIs... at least based on my limited experience thus far. Still, I am not sure the problem lies with the serial code alone. async_read_until's behavior does not conform to its documentation-- that is certainly a bug. This is from the Boost.Asio async_read_until docs: Parameters: ... void handler( // Result of operation. const boost::system::error_code& error, // The number of bytes in the streambuf's get // area up to and including the delimiter. // 0 if an error occurred. std::size_t bytes_transferred ); If I'm interpreting this correctly, error and bytes_transferred cannot be errorless and 0, respectively. This is exactly the behavior I'm observing. The question is, I guess, what is causing this. Like you said, it could very well be a bug in Windows that is leaking through the Boost.Asio implementation of async_read_until. Regardless of whose fault it is, currently async_read_until does not conform to its documentation. I'll keep probing at it as work permits, but I'm unfamiliar with most of Windows's APIs so I have my doubts that I'll be able to trace the problem. Thanks for the help!
participants (2)
-
Marcano, Gabriel E
-
Niall Douglas