Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ThreadAbort on Unix and reenable the related tests #73399

Merged
merged 5 commits into from
Aug 6, 2022

Conversation

janvorli
Copy link
Member

@janvorli janvorli commented Aug 4, 2022

When the HandleSuspensionForInterruptedThread invokes Thread::HandleThreadAbort
and the thread abort exception is thrown from there, runtime fails with
unhandled C++ exception because there was a missing guard that catches the
PAL_SEHException and invokes DispatchManagedException to propagate it further
through managed code.
This change fixes that and also addresses an issue with activation injection
in Thread::UserAbort in the case of infinite timeout (it would not inject the
activation in that case).

It also reenables the controlled execution tests on Unix.

I have tested it on both Unix and CET enabled Windows.

@janvorli janvorli added this to the 7.0.0 milestone Aug 4, 2022
@janvorli janvorli self-assigned this Aug 4, 2022
@janvorli
Copy link
Member Author

janvorli commented Aug 4, 2022

I recommend reviewing with whitespace comparison disabled, I've again changed indentation of a large block of a code that makes the change look much larger (https://github.com/dotnet/runtime/pull/73399/files?w=1)

When the HandleSuspensionForInterruptedThread invokes Thread::HandleThreadAbort
and the thread abort exception is thrown from there, runtime fails with
unhandled C++ exception because there was a missing guard that catches the
PAL_SEHException and invokes DispatchManagedException to propagate it further
through managed code.
This change fixes that and also addresses an issue with activation injection
in Thread::UserAbort in the case of infinite timeout (it would not inject the
activation in that case).
UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
UNINSTALL_MANAGED_EXCEPTION_DISPATCHER;

frame.Pop(pThread);
Copy link
Member

Choose a reason for hiding this comment

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

Should we pop the frame right after PulseGCMode() ?
Is the frame used by the thread abort throw?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it is used by the thread abort throw, that's why it is at this place.

pThread->UnmarkRedirectContextInUse(m_Regs);
m_Regs = NULL;
if (pThread->UnmarkRedirectContextInUse(m_Regs))
{
Copy link
Member

Choose a reason for hiding this comment

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

Here - can we just check UseContextBasedThreadRedirection() and if not, then not call Unmark and not assign null?

Copy link
Member

@VSadov VSadov left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks!

}
void NeedStackCrawl()
{
m_pThread->SetThreadState(Thread::TS_StackCrawlNeeded);
Copy link
Member

Choose a reason for hiding this comment

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

Nit: This assumes NeedStackCrawl is never called on a non-Activated instance. We might want to add an assert or a check here.

@janvorli
Copy link
Member Author

janvorli commented Aug 5, 2022

There is a problem on Alpine Linux, all three architectures crash in the thread abort tests. I am investigating it.

On Alpine Linux, libunwind cannot unwind correctly over signal frames. We have been
handling that for hardware exceptions, but with the new possibility of thread abort
exception being thrown from the activation handler, we need to apply the same treatment
to the activation signal too. We save a location of the windows style context in the
activation_injection_handler and a return address in this function for a call to the
actual registered handler invocation. Then in PAL_VirtualUnwind, when we detect that
we are trying to unwind from this location, we use the saved context instead of calling
libunwind.
@janvorli
Copy link
Member Author

janvorli commented Aug 5, 2022

Fixed the issue

@janvorli
Copy link
Member Author

janvorli commented Aug 6, 2022

The CI failure is #73247

@janvorli janvorli merged commit 11862b3 into dotnet:main Aug 6, 2022
@janvorli janvorli deleted the fix-unix-threadabort branch August 6, 2022 08:10
@ghost ghost locked as resolved and limited conversation to collaborators Sep 5, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants