#12340 closed Bugs (worksforme)
Combining boost::context and SEH doesn't work
Reported by: | Owned by: | olli | |
---|---|---|---|
Milestone: | To Be Determined | Component: | context |
Version: | Boost 1.61.0 | Severity: | Problem |
Keywords: | Cc: |
Description
This piece of code should print "hi!", but it does not. Compiler: Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24210 for x64
How to compile it: cl test.cpp /MD /EHsc /I F:\repos\boost\include\boost-1_61 F:\repos\boost\lib\libboost_context-vc140-mt-1_61.lib
Boost was built using: .\b2 address-model=64 asmflags=\safeseh --prefix=F:\repos\boost install
Attachments (2)
Change History (11)
by , 6 years ago
comment:1 by , 6 years ago
Summary: | Combining boot::context, SEH and C++ exceptions doesn't work → Combining boost::context and SEH doesn't work |
---|
comment:2 by , 6 years ago
Resolution: | → worksforme |
---|---|
Status: | new → closed |
SEH works for me on 32bit/64bit Windows - see added unit-test (branch develop)
follow-up: 4 comment:3 by , 6 years ago
Does test_correct.cpp work for you? I know SEH works when there are not threads involved. But as soon as I add threads things start failing.
comment:4 by , 6 years ago
Replying to anonymous:
Does test_correct.cpp work for you? I know SEH works when there are not threads involved. But as soon as I add threads things start failing.
I've changed the unit-test - now execution_context is executed in a std::thread. Works for me. I did not use your example - but it is equivalent.
follow-up: 6 comment:5 by , 6 years ago
The difference is that my test produces a stack overflow that is not caught. If I replace rec() with a null ptr dereference or a división by zero everything works alright.
I am running Windows 10 with the lastest updates, just in case it matters.
comment:6 by , 6 years ago
Replying to anonymous:
The difference is that my test produces a stack overflow that is not caught.
Maybe you should use protected_fixedsize stack-allocator: http://www.boost.org/doc/libs/1_61_0/libs/context/doc/html/context/stack/protected_fixedsize.html The stack-allocator adds an protected page (virtual memory) at the end of each stack. Please report if it works for you.
follow-up: 8 comment:7 by , 6 years ago
It does not work. I am using SEH to implement a stack allocator that enlarges the stack after an access violation. I was able to reduce my code to the small test in test_correct.cpp I am thinking that since SEH only fails when the exception is caused by an illegal access to the bottom of the stack it may be a code generation bug. Especially since divisions by zero are correcty caught by the SEH handler.
comment:8 by , 6 years ago
Replying to anonymous:
I am using SEH to implement a stack allocator that enlarges the stack after an access violation.
A Micorosoft principal told me that Windows requires/forces a contiguous stack - extending the stack after an access violation might not work in principle.
comment:9 by , 6 years ago
Mmmmh, that's good to know.
It seems to contradict what this example shows:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366803(v=vs.85).aspx
This sample does not show how to use the guard page fault to "grow" a dynamic array, such as a stack.
It implies that it is possible to enlarge a stack after a guard page fault.
https://blogs.msdn.microsoft.com/oldnewthing/20060927-07/?p=29563/
Explains that normal stack growth is implemented using guard pages, so it must be legal to extend a stack.
Also note that the test does not enlarge the stack at all. It simply should detect the page fault and leave the function.
There is something in boost::context that prevents the SEH code from catching access violations to the bottom of the stack.
I made discovery: if at the bottom of the stack there are at least 3 guard pages Windows will automatically extend the stack without ever letting the exception reach the exception handler, but when it runs out of guard pages it will throw a STATUS_STACK_OVERFLOW exception. If at the bottom of the stack there is a page marked PAGE_NOACCESS or if there are fewer than 3 guard pages a STATUS_ACCESS_VIOLATION exception will be thrown which won't pass through the exception filter (this is what IMHO is a bug).
I changed the parameters of the VirtualProtect call in protected_fixedsize_stack.hpp
VirtualProtect(vp, traits_type::page_size() '''* 3''', PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
test case.