This is an archive of the discontinued LLVM Phabricator instance.

[EH] Keep filter types even if the type has been caught.
ClosedPublic

Authored by andrew.w.kaylor on Nov 13 2015, 5:23 PM.

Details

Summary

I came across a problem in testing on Linux where the handling of unexpected exception types wasn't working correctly if the unexpected handler tried to throw a type that the call site would have caught. The following code demonstrates the issue:

#include <exception>
#include <iostream>
#include <cstdlib>

void unexpected() {
  std::cout << "Throwing in unexpected(): 1\n";
  throw 1;
}

void foo() throw (int) {
  std::set_unexpected(unexpected);
  try {
    std::cout << "Throwing in foo(): 2.0\n";
    throw 2.0;
  } catch (int i) {
    std::cout << "Caught in foo(): " << i << "\n";
    exit(EXIT_FAILURE);
  }
}

int main() {
  try {
    foo();
  } catch (int i) {
    std::cout << "Caught in main(): " << i << "\n";
  } catch (...) {
    std::cout << "Caught in main(): catch all\n";
    exit(EXIT_FAILURE);
  }
  return 0;
}

The "2.0" exception thrown in foo should go to the unexpected handler and the '1' exception thrown by the unexpected handler should be caught by the 'int' handler in main. Instead, without my proposed changes the runtime library calls terminate() when '1' is thrown from the unexpected handler. Near as I can tell, the runtime is looking at the exception record for the call site in the LSDA when the unexpected handler throws an exception to see if the throw exception meets the call site's filter requirements.

The STL documentation for std::set_unexpected() says this: "The unexpected handler function can handle the exception and shall end either by terminating (calling terminate or some other method, such as exit or abort) or by throwing an exception (even rethrowing the same exception again). If the exception thrown (or rethrown) is not in the function's dynamic-exception-specification but bad_exception is, a bad_exception is thrown. Otherwise, if the new exception is not in the dynamic-exception-specification either, terminate is automatically called."

I'm not certain that this is an issue for Objective C and I'm not sure how to test that. I'm just guessing that it might be similar, but I will happily exclude it if it doesn't apply. I also don't know if this problem applies to any other personality functions, but given how long the code has been in its current state I would guess not.

Diff Detail

Repository
rL LLVM

Event Timeline

andrew.w.kaylor retitled this revision from to [EH] Keep filter types even if the type has been caught..
andrew.w.kaylor updated this object.
andrew.w.kaylor added reviewers: rnk, majnemer, rjmccall.
andrew.w.kaylor set the repository for this revision to rL LLVM.
andrew.w.kaylor added a subscriber: llvm-commits.
rjmccall edited edge metadata.Nov 13 2015, 7:01 PM

The fix should apply to all personalities (including the ObjC ones). I'm sure the bug has nothing to do with specific personalities and everything to do with nobody really bothering to do more than minimal testing.

andrew.w.kaylor edited edge metadata.

Updating to apply fix to all personality functions.

This revision was automatically updated to reflect the committed changes.