Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Try to fix issue 19831 without understanding by copying the behavior from __dmd_personality_v0 #2602

Merged
merged 1 commit into from
May 16, 2019

Conversation

FeepingCreature
Copy link
Contributor

@FeepingCreature FeepingCreature commented May 10, 2019

NOT feeling good about this. Seems to work though???

Mostly opening this PR so tests get run.

This was not arrived at through any kind of insight, but mostly by flailing around.

Ping @donc . Help us Don Clugston, you're our only hope.

edit: @kinke ping? ("No. There is another.")

@dlang-bot
Copy link
Contributor

dlang-bot commented May 10, 2019

Thanks for your pull request and interest in making D better, @FeepingCreature! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the annotated coverage diff directly on GitHub with CodeCov's browser extension
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Auto-close Bugzilla Severity Description
19831 major throw/catch in scope(exit) crashes with illegal instruction

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub fetch digger
dub run digger -- build "stable + druntime#2602"

@dlang-bot dlang-bot added the Bug Fix Include reference to corresponding bugzilla issue label May 10, 2019
@FeepingCreature
Copy link
Contributor Author

oh no they're passing

@FeepingCreature
Copy link
Contributor Author

Note from IRL: @ibuclaw looked it over and thinks it's basically sound, he might have some time tomorrow at the Hackathon to get it documented a bit better.

@donc
Copy link

donc commented May 11, 2019

Note that I only wrote the original Windows exception chaining, I don't know anything about how the Linux exception handler works. Does this bug apply to Windows as well?
BTW despite having implemented it, I think that exception chaining is a really, really bad idea. I don't think anybody would ever want to look at the exception chain, and it creates a host of problems.

@FeepingCreature
Copy link
Contributor Author

FeepingCreature commented May 11, 2019

Walter also said that exception chaining should be removed and we should go back to C++ and crashing on throw-in-finally.

I must strenuously object to at least that last part - scope(exit) is a core, heavily advertised feature of D and it'll look terrible (and basically make it unusable) if a basic feature like exceptions causes crashes inside it.

(I found this bug when I was looking at a case where I wanted to see the chained exception btw, and was upset it wasn't shown.)

@FeepingCreature
Copy link
Contributor Author

Re Windows: I tried with wine+DMDwin32 and at least in that configuration, the problem does not occur.

@ibuclaw
Copy link
Member

ibuclaw commented May 11, 2019

I think there needs to be a few more tests. See eh.d exception chaining tests, but adapt as you do here to trigger the bug.

@FeepingCreature
Copy link
Contributor Author

FeepingCreature commented May 11, 2019

I don't understand what you mean. eh.d exception chaining tests clearly did not trigger the bug. Should I just rewrite eh.d to be "eh.d, but every finally throws and catches an exception"?

You already can't catch in finally directly. I'm not sure how else you could order these elements to produce a test.

@FeepingCreature
Copy link
Contributor Author

ping @ibuclaw

@ibuclaw
Copy link
Member

ibuclaw commented May 13, 2019

@FeepingCreature there is a slight distinction between those tests and this test.

In eh.d you have:

void collideone()
{
    try
    {
        throw new Exception("x");
    }
    finally
    {
        throw new Exception("y");
    }
}

This test is:

void collideone()
{
    try
    {
        throw new Exception("x");
    }
    finally
    {
        funcThatThrowsAndCatches();
    }
}

I think that those tests could be copied to your new test file and amended as needed to check that the various weird chain cases and this mix well.

@FeepingCreature
Copy link
Contributor Author

I'll take a look tomorrow.

@FeepingCreature
Copy link
Contributor Author

FeepingCreature commented May 14, 2019

@ibuclaw Is this better? It's hard to write comments and tests for code that I don't understand how it works. Since you said you did (:+1:), are the comments right like this?

Copy link
Member

@ibuclaw ibuclaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable, and tests look good.

//printf("start: %p '%.*s'\n", ehobject, ehobject.classinfo.info.name.length, ehobject.classinfo.info.name.ptr);
for (ExceptionHeader* ehn = eh.next; ehn; ehn = ehn.next)
{
// like __dmd_personality_v0, don't combine when the exceptions are from different functions
// (fixes issue 19831, exception thrown and caught while inside finally block)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, if a function has been partitioned, this will also not match.

However this will never happen with dmd, and gdc turns off partitioning unless the optimization is explicitly requested on the command line.

Copy link
Contributor Author

@FeepingCreature FeepingCreature May 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

....

throws up hands

I GUESS?!?

Copy link
Contributor

@kinke kinke May 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This broke runnable/eh.d for LDC [with its slight modifications in this file]. The testsuite passes again when NOT breaking here as long as currentLsd is null (if (currentLsd && currentLsd != ehn.languageSpecificData) ...), but I have no idea whether that's correct. @ibuclaw: any thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would it be null?

Copy link
Contributor

@kinke kinke May 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT, each ExceptionHeader.languageSpecificData starts out with null and is only set after finding a matching handler/catch in the search phase (and only for D exceptions).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well the lsda is known since the beginning of the personality function, you could either eagerly set it, or pass it onto getClassInfo to initialize cuurentLsd with.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the question is rather 'why does DMD have no problem with it'. I'll pass it through; pls ping me if GDC has problems too, so that we can come up with something here upstream.

@donc
Copy link

donc commented May 15, 2019

I would like to see a test where the exception is thrown in one function and caught in another. If this works, your PR has my blessing.

void thrower()
{
   throw new Exception("a");
}

void functhatthrowsandslowlycatches()
{
     try {
         thrower();
    }
    catch(Exception e){}
}

void test5()
{
   try {
      throw new Exception("x");
   }
   finally {  
      functhatthrowsandslowlycatches();
  }
}

@FeepingCreature
Copy link
Contributor Author

@donc See test5. Seems to work.

@donc
Copy link

donc commented May 16, 2019

LGTM.

@thewilsonator
Copy link
Contributor

As this fixes a severity major bug it should go in stable, unless you don't feel confident about doing so.

… to __dmd_personality_v0 (ignoring in-flight exceptions that we haven't collided with yet)
@FeepingCreature FeepingCreature changed the base branch from master to stable May 16, 2019 05:33
@dlang-bot dlang-bot merged commit 7c5464e into dlang:stable May 16, 2019
@FeepingCreature FeepingCreature deleted the fix/issue-19831 branch May 16, 2019 13:35
kinke added a commit to ldc-developers/druntime that referenced this pull request May 25, 2019
kinke added a commit to ldc-developers/druntime that referenced this pull request May 27, 2019
After dlang#2602; no idea why DMD doesn't have a problem with
it.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Fix Include reference to corresponding bugzilla issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants