Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#12340 closed Bugs (worksforme)

Combining boost::context and SEH doesn't work

Reported by: nicolasbertolo@… 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)

test.cpp (439 bytes ) - added by anonymous 6 years ago.
test case.
test_correct.cpp (844 bytes ) - added by anonymous 6 years ago.
ignore previous test please.

Download all attachments as: .zip

Change History (11)

by anonymous, 6 years ago

Attachment: test.cpp added

test case.

comment:1 by anonymous, 6 years ago

Summary: Combining boot::context, SEH and C++ exceptions doesn't workCombining boost::context and SEH doesn't work

by anonymous, 6 years ago

Attachment: test_correct.cpp added

ignore previous test please.

comment:2 by olli, 6 years ago

Resolution: worksforme
Status: newclosed

SEH works for me on 32bit/64bit Windows - see added unit-test (branch develop)

comment:3 by anonymous, 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.

in reply to:  3 comment:4 by olli, 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.

comment:5 by anonymous, 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.

in reply to:  5 comment:6 by olli, 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.

Last edited 6 years ago by olli (previous) (diff)

comment:7 by anonymous, 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.

in reply to:  7 comment:8 by olli, 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 anonymous, 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);
Note: See TracTickets for help on using tickets.