New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't catch Boost.Asio exceptions inside coroutines #1559
Comments
I can reproduce your error. It can be related to exceptions handling. 32 bit and 64 bit targets use different exceptions handling. To debug this, can you build your application in 64-bit mode (target x86_64-w64-mingw32.static) and check how it works, please? There is a feature request to support non-standard exception handlings. See also gcc configure flags to change this. I am trying to build with |
|
Same error with boost 1.62 |
By the way, an example of throwing from a coroutine works. |
Thanks, I also tried a lot of combinations of thread models, exceptions, 32/64 bits, turned GCC optimizations on and off etc. In the end, nothing helped. And yes, regular exceptions (std::runtime_error, for instance) can be caught just fine, only asio's ones fall through. So it's not like it is completely broken but something between asio and MinGW just doesn't work right. |
Forgot to mention, there's a subtle discrepancy between the program behavior on Linux and on Windows. When ran under gdb on Linux, the test program only spawns one thread it seems. On Windows it spawns three. I suspect that's happening because Boost is compiled as multithreaded in MXE (the exception is thrown in another thread and can't be caught in the handler set up in the main thread) but I was unable to build it singlethreaded, got some obscure error messages. Is there a way to build singlethreaded Boost in MXE? |
Ok, for now I've come up with a simple yet effective solution, it's to use yield[ec] form that doesn't throw. After each async call I may use if (ec) throw boost::system::system_error(ec); which is effectively what's used in impl/spawn.hpp inside asio. For a reason unknown to me this works just as expected. I checked the thread id from which the asio exception is thrown and compared it to the main thread id and they seem to be equal. |
I tried this: diff --git a/src/boost.mk b/src/boost.mk
index 71e38fa..ed3c804 100644
--- a/src/boost.mk
+++ b/src/boost.mk
@@ -41,8 +41,7 @@ define $(PKG)_BUILD
binary-format=pe \
link=$(if $(BUILD_STATIC),static,shared) \
target-os=windows \
- threadapi=win32 \
- threading=multi \
+ threading=single \
variant=release \
toolset=gcc-mxe \
cxxflags=$(if $(findstring posix,$(MXE_GCC_THREADS)),-std=gnu++11,-std=gnu++98) \
@@ -63,21 +62,4 @@ define $(PKG)_BUILD
# setup cmake toolchain
echo 'set(Boost_THREADAPI "win32")' > '$(CMAKE_TOOLCHAIN_DIR)/$(PKG).cmake'
-
- '$(TARGET)-g++' \
- -W -Wall -Werror -ansi -U__STRICT_ANSI__ -pedantic \
- '$(PWD)/src/$(PKG)-test.cpp' -o '$(PREFIX)/$(TARGET)/bin/test-boost.exe' \
- -DBOOST_THREAD_USE_LIB \
- -lboost_serialization-mt \
- -lboost_thread_win32-mt \
- -lboost_system-mt \
- -lboost_chrono-mt
-
- # test cmake
- mkdir '$(1).test-cmake'
- cd '$(1).test-cmake' && '$(TARGET)-cmake' \
- -DPKG=$(PKG) \
- -DPKG_VERSION=$($(PKG)_VERSION) \
- '$(PWD)/src/cmake/test'
- $(MAKE) -C '$(1).test-cmake' -j 1 install
endef And compiled with the following command:
Note that Boost.Context is still in multi-threaded mode. But it fails with the same error (tested in wine):
|
Then that's not it, thanks for testing and confirming. My workaround with yield[ec] worked good enough so I'll just stick to it until the real culprit is found. |
@starius, the way to enable dw2 is to disable sjlj:
There's a comment that it works with posix-dwarf-boost 1.62. It also seems that 1.62 fixed the issue with With current 1.60 and enable exceptions patch
running on Win7
Testing i686-w64-mingw32.static.posix and i686-w64-mingw32.static now. |
Oh, good to know, thanks! Although I've already changed my code to use the mentioned workaround, I'd much like to revert it back so it's easier to read and use. |
So it seems that With #1664 you can do
|
@starius wrote #1559 (comment):
same is true for @rkfg #1664 is merged now so you can use the |
@tonytheodore Thanks a lot, will try it when I can (currently working on another project)! |
I tested the dw2 variant and got this on Wine:
On a real Windows installation it reports an unknown host so it's probably not an issue. Both Wine and Windows don't get terminated because of an uncaught exception so on the 32-bit side it seems to be fixed. However, x86_64 build (with dw2 exceptions) crashes at startup on both Wine and Windows. Is this not supported at the moment? Because I'd like to be able to build both 32 and 64 bit binaries with Asio exceptions working. |
There's no dw2 exceptions on x86_64, there's seh (default) and sjlj. Both crash on launch without producing any output. |
Crashing in different ways with v1.63:
|
If anyone's still interested, I've updated the test program to be compiled with the recent Boost 1.67 (they added a template parameter to |
I've posted this to Boost and Boost.Asio mailing lists and they said it could be compiler's fault. So I repost here hoping someone would shed some light on the issue.
I have this little example of Boost.Asio code:
It works as expected on Linux producing
1
2
Caught Host not found (authoritative)
but on Windows it crashes with:
1
2
terminate called after throwing an instance of 'boost::system::system_error' what(): Unknown error
Tested on Windows Server 2008, Windows 7 and Wine, everything is the same. I'm compiling on Linux for Windows with MXE on GCC 4.9.4, Boost version is 1.60.0. I'm really stuck at this point as nothing in Google looks a valid solution for the case and I already have a working application on Linux but it crashes on any network error on Windows.
I also tried to disable Asio's threads with #define BOOST_ASIO_DISABLE_THREADS but that resulted in Asio's inability to start a background thread for asynchronous name resolution (that exception is caught fine).
The text was updated successfully, but these errors were encountered: