[WinEH] A hiccup for the Windows C++ exception handling

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

[WinEH] A hiccup for the Windows C++ exception handling

Kaylor, Andrew

I’ve been working recently to get the following test case working for an x86_64-pc-windows-msvc target.

 

void test1() {

  try {

    try {

      throw 1;

    } catch(...) {

      throw;

    }

  } catch (...) {

  }

}

 

I committed a patch earlier in the week to get the WinEHPrepare pass to produce IR that I thought was sufficient, but as I mentioned in the review I was still seeing runtime errors when executing a program compiled with this code.  I have since figured out why the program crashes at runtime, but fixing it is going to be a bit tricky.  It has to do with some wrinkles in how the Microsoft runtime handles the rethrown exceptions.

 

As the code above is written, the outer catch should handle both the inner catch and its try-block and the outer catch handler should return to a location in the parent function.

 

An ideal numbering of the EH states would look something like this:

 

void test1() {

  // EH state = -1

  try {

    // EH state = 0

    try {

      // EH state = 1

      throw 1;

    } catch(...) {

      // EH state = 2

      throw;

    }

    // EH state = 0

  } catch (...) {

    // EH state = 3

  }

  // EH state = -1

}

 

That would give us the following try map entries:

 

Inner catch { TryLow = 1, TryHigh = 1, CatchHigh = 2 }

Outer catch { TryLow = 0, TryHigh = 2, CatchHigh = 3 }

 

Unfortunately, we can’t deduce this from the IR because the outer catch handler is only ever seen to catch exceptions from within the inner catch.  So we end up producing a try map like this. (Even this requires a small patch to the current code to avoid dropping the second entry entirely.)

 

Inner catch { TryLow = 1, TryHigh = 1, CatchHigh = 3 }

Outer catch { TryLow = 2, TryHigh = 2, CatchHigh = 3 }

 

This causes the runtime to interpret the outer catch as if it were nested within the inner catch.  In other words, the code is indistinguishable from this:

 

void test2() {

  try {

    throw 1;

  } catch(...) {

    try {

      throw;

    } catch (...) {

    }

  }

}

 

And indeed, the prepared IR we produce for these two cases is the same.  (There is a critical difference before WinEHPrepare that I’ll discuss in a bit.)

 

Here is where the runtime problem comes in.  Because the runtime thinks the second catch is nested within the first, it doesn’t actually rethrow the exception.  It just passes it on to the second handler, which it expects to return to an address within the first catch handler.  However, we aren’t currently generating code that does that (in either case) because when we outline the first handler we insert a stub for the nested handler and without knowing what the second handler does, the block to which it should return appears to be unreachable.

 

Knowing this, I can fix the simple case easily enough by changing the order in which the landing pads are processed so that I don’t need to stub out the nested handler and can use its return targets to make the required block reachable. 

 

However, this opens a huge can of worms for non-trivial cases.  There are scenarios (the original test case among them) where a nested handler should return to an block outside the enclosing handler.  So how can the enclosing handler determine which blocks it should clone and which it shouldn’t?  I’m working on this now, but it is quickly becoming clear that our current cloning scheme is not well suited to handle it.

 

So there are two issues here.

 

1) We need a better way to figure out which blocks should be in which handlers and properly remap the return statements in each handler accordingly.

2) We need a better way to compute the EH states.

 

Anyway, I’m working on these problems right now.  I’m still trying to solve the problems without redesigning our current scheme, but I don’t think this is going to be the right long term solution.

 

Thoughts?

 

-Andy

 


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [WinEH] A hiccup for the Windows C++ exception handling

Reid Kleckner-2
On Wed, May 13, 2015 at 11:03 AM, Kaylor, Andrew <[hidden email]> wrote:

So there are two issues here.

 

1) We need a better way to figure out which blocks should be in which handlers and properly remap the return statements in each handler accordingly.

2) We need a better way to compute the EH states.

 

Anyway, I’m working on these problems right now.  I’m still trying to solve the problems without redesigning our current scheme, but I don’t think this is going to be the right long term solution.


Yeah, we're on the same page. The current scheme is not the right long term solution. The SEH personality functions are not nearly as limiting. I was hoping that, like with SEH, we could completely throw away the information about try nesting and simply emit tables that are functionally correct. We knew it was theoretically impossible to always recover the nested try structure from Itanium-style landingpad IR, but now we know it is also *practically* impossible. :)

Ultimately, I think something like the dispatchblock scheme I described will work better.

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [WinEH] A hiccup for the Windows C++ exception handling

Kaylor, Andrew

Have got anything started with the dispatchblock plan?

 

From: Reid Kleckner [mailto:[hidden email]]
Sent: Wednesday, May 13, 2015 1:15 PM
To: Kaylor, Andrew
Cc: David Majnemer <[hidden email]> ([hidden email]); LLVM Developers Mailing List
Subject: Re: [WinEH] A hiccup for the Windows C++ exception handling

 

On Wed, May 13, 2015 at 11:03 AM, Kaylor, Andrew <[hidden email]> wrote:

So there are two issues here.

 

1) We need a better way to figure out which blocks should be in which handlers and properly remap the return statements in each handler accordingly.

2) We need a better way to compute the EH states.

 

Anyway, I’m working on these problems right now.  I’m still trying to solve the problems without redesigning our current scheme, but I don’t think this is going to be the right long term solution.

 

Yeah, we're on the same page. The current scheme is not the right long term solution. The SEH personality functions are not nearly as limiting. I was hoping that, like with SEH, we could completely throw away the information about try nesting and simply emit tables that are functionally correct. We knew it was theoretically impossible to always recover the nested try structure from Itanium-style landingpad IR, but now we know it is also *practically* impossible. :)

 

Ultimately, I think something like the dispatchblock scheme I described will work better.


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [WinEH] A hiccup for the Windows C++ exception handling

Reid Kleckner-2
Basically, I'm trying to come up with a good design doc with David right now so I can mail it out. :)

On Wed, May 13, 2015 at 1:43 PM, Kaylor, Andrew <[hidden email]> wrote:

Have got anything started with the dispatchblock plan?

 

From: Reid Kleckner [mailto:[hidden email]]
Sent: Wednesday, May 13, 2015 1:15 PM
To: Kaylor, Andrew
Cc: David Majnemer <[hidden email]> ([hidden email]); LLVM Developers Mailing List
Subject: Re: [WinEH] A hiccup for the Windows C++ exception handling

 

On Wed, May 13, 2015 at 11:03 AM, Kaylor, Andrew <[hidden email]> wrote:

So there are two issues here.

 

1) We need a better way to figure out which blocks should be in which handlers and properly remap the return statements in each handler accordingly.

2) We need a better way to compute the EH states.

 

Anyway, I’m working on these problems right now.  I’m still trying to solve the problems without redesigning our current scheme, but I don’t think this is going to be the right long term solution.

 

Yeah, we're on the same page. The current scheme is not the right long term solution. The SEH personality functions are not nearly as limiting. I was hoping that, like with SEH, we could completely throw away the information about try nesting and simply emit tables that are functionally correct. We knew it was theoretically impossible to always recover the nested try structure from Itanium-style landingpad IR, but now we know it is also *practically* impossible. :)

 

Ultimately, I think something like the dispatchblock scheme I described will work better.



_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [WinEH] A hiccup for the Windows C++ exception handling

Kaylor, Andrew

I made some progress this afternoon.  I now have a set of changes in my local sandbox that allows clang to pass all of the tests in the suite I’ve been using to exercise this code.

 

How do you feel about working these changes into trunk to establish a working baseline, even knowing that parts of this are going to be redesigned?

 

-Andy

 

From: Reid Kleckner [mailto:[hidden email]]
Sent: Wednesday, May 13, 2015 2:16 PM
To: Kaylor, Andrew; David Majnemer
Cc: LLVM Developers Mailing List
Subject: Re: [WinEH] A hiccup for the Windows C++ exception handling

 

Basically, I'm trying to come up with a good design doc with David right now so I can mail it out. :)

 

On Wed, May 13, 2015 at 1:43 PM, Kaylor, Andrew <[hidden email]> wrote:

Have got anything started with the dispatchblock plan?

 

From: Reid Kleckner [mailto:[hidden email]]
Sent: Wednesday, May 13, 2015 1:15 PM
To: Kaylor, Andrew
Cc: David Majnemer <[hidden email]> ([hidden email]); LLVM Developers Mailing List
Subject: Re: [WinEH] A hiccup for the Windows C++ exception handling

 

On Wed, May 13, 2015 at 11:03 AM, Kaylor, Andrew <[hidden email]> wrote:

So there are two issues here.

 

1) We need a better way to figure out which blocks should be in which handlers and properly remap the return statements in each handler accordingly.

2) We need a better way to compute the EH states.

 

Anyway, I’m working on these problems right now.  I’m still trying to solve the problems without redesigning our current scheme, but I don’t think this is going to be the right long term solution.

 

Yeah, we're on the same page. The current scheme is not the right long term solution. The SEH personality functions are not nearly as limiting. I was hoping that, like with SEH, we could completely throw away the information about try nesting and simply emit tables that are functionally correct. We knew it was theoretically impossible to always recover the nested try structure from Itanium-style landingpad IR, but now we know it is also *practically* impossible. :)

 

Ultimately, I think something like the dispatchblock scheme I described will work better.

 


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [WinEH] A hiccup for the Windows C++ exception handling

Reid Kleckner-2
On Wed, May 13, 2015 at 4:37 PM, Kaylor, Andrew <[hidden email]> wrote:

I made some progress this afternoon.  I now have a set of changes in my local sandbox that allows clang to pass all of the tests in the suite I’ve been using to exercise this code.

 

How do you feel about working these changes into trunk to establish a working baseline, even knowing that parts of this are going to be redesigned?


I guess I'm kind of ambivalent about continuing in the current direction. It doesn't hurt, but if it provides someone with basic functionality for now, then that's OK. On the other hand, the tests won't be particularly valuable because Clang is going to emit new LLVM IR, so they'll need to be redone.

I also think that, given that the rewrite will take at least a month, we should turn MSVC C++ exceptions off by default in Clang until it's ready. We need some hidden flag that isn't /EHs. I'm already tired of getting bug reports along the lines of "clang crashed while compiling MSVC-style exceptions". Of course, the user can't tell from the crash that the workaround is just "turn off exceptions until they work". =/

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: [WinEH] A hiccup for the Windows C++ exception handling

Kaylor, Andrew

I should clarify that the tests I’m talking about are compile-and-execute tests, so they will still be relevant to the re-designed implementation.  Unfortunately, I don’t have them integrated with any LLVM testing mechanism.  That’s something else I’ve been meaning to ask about.

 

Anyway, I think the results I’m seeing now are fairly significant, so I’d like to get these changes checked in -- especially given that it’s going to be a month or more before an alternate approach is ready.  I’d also like to talk about a transition plan so that we can minimize the backward steps taken as this is redesigned.  Maybe a command line option to enable the new IR generation until an end-to-end implementation is complete?

 

I’m working right now to clean up what I’ve done, but I should have it in a reviewable state today.  After that, I’ll try to create some lit-based tests that exercise the trouble spots that I am addressing.

 

I don’t have any objections to turning MSVC C++ exceptions off by default, but I think it’s possible that with these changes that might not be necessary.

 

-Andy

 

From: Reid Kleckner [mailto:[hidden email]]
Sent: Thursday, May 14, 2015 9:12 AM
To: Kaylor, Andrew
Cc: David Majnemer; LLVM Developers Mailing List
Subject: Re: [WinEH] A hiccup for the Windows C++ exception handling

 

On Wed, May 13, 2015 at 4:37 PM, Kaylor, Andrew <[hidden email]> wrote:

I made some progress this afternoon.  I now have a set of changes in my local sandbox that allows clang to pass all of the tests in the suite I’ve been using to exercise this code.

 

How do you feel about working these changes into trunk to establish a working baseline, even knowing that parts of this are going to be redesigned?

 

I guess I'm kind of ambivalent about continuing in the current direction. It doesn't hurt, but if it provides someone with basic functionality for now, then that's OK. On the other hand, the tests won't be particularly valuable because Clang is going to emit new LLVM IR, so they'll need to be redone.

 

I also think that, given that the rewrite will take at least a month, we should turn MSVC C++ exceptions off by default in Clang until it's ready. We need some hidden flag that isn't /EHs. I'm already tired of getting bug reports along the lines of "clang crashed while compiling MSVC-style exceptions". Of course, the user can't tell from the crash that the workaround is just "turn off exceptions until they work". =/


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev