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

runtime: don't crash in exception handler on windows/arm64 #50877

TopperDEL opened this issue Jan 28, 2022 · 4 comments

runtime: don't crash in exception handler on windows/arm64 #50877

TopperDEL opened this issue Jan 28, 2022 · 4 comments
arch-arm64 NeedsInvestigation OS-Windows


Copy link

@TopperDEL TopperDEL commented Jan 28, 2022

I have a quite complex bug but together with @marler8997 we found a workaround.

I tried to get a go-library working on a Hololens 2 via .Net. So I build the library into a dll using the awesome zig-compiler, and then tried to PInvoke into it from C#/.Net. I did all this already successfull on Windows, Linux, MacOs, Android and iOs.

On Hololens, though, my app always crashed whenever the UWP (Universal Windows Platform) DLL came together with the go-runtime. We know found out that Go seems to try to handle an exception thrown from UWP and fails to do so leading to a "badsignal" and an application crash.

@marler8997 helped me with an many in-depth-sessions debugging assembly code and created that patch:

May someone with knowledge of the win-arm64-build if this is a good solution or if there might be a better way of doing it? Thank you very much!

What version of Go are you using (go version)?


Does this issue reproduce with the latest release?


What operating system and processor architecture are you using (go env)?

Windows, ARM64, Hololens 2

@ALTree ALTree changed the title Win/ARM64: don't crash in exception handler runtime: don't crash in exception handler on windows/arm64 Jan 28, 2022
@ALTree ALTree added the NeedsInvestigation label Jan 28, 2022
Copy link

@ALTree ALTree commented Jan 28, 2022

cc @cherrymui @mknyszek (my guess)

Copy link

@marler8997 marler8997 commented Jan 28, 2022

This comment from @ianlancetaylor seems very relevant here: #12465 (comment)

This is the Go signal handler receiving a SIGCHLD signal. It's not a problem for getg to return nil in sigtrampgo. That just means that a signal occurred on a non-Go thread.

But this comment contradicts what the sigtramp code is doing. If getg returns nil, sigtramp calls badsignal2 which calls abort causing an AccessViolation. If Ian's comment is still correct today (it was made in 2015) then this is indeed a bug in sigtramp.

My workaround was jut to modify sigtramp to return 0 when getg returns nil (marler8997@f645ec0). On windows this tells the caller that the exception is not handled and to continue to the next handler, which may be the functionality we want here.

It's also interesting to note the naming of this function sigtramp. This is a vestigal to linuxy platforms where programs need to register a special "trampoline" function to make signals work. This is not the case on windows as the "trampoline" functionality is already provided by other means. Instead executables can register callback functions without setting up a trampoline and already has a mechanism to support multiple callbacks and a way to stop/continue through them. The simple solution of returning when getg returns nil may actually be correct on Windows.

Also note that I see arm32 does the same thing here, so if this fix is correct then it should probably go to arm32 as well.

Copy link

@ianlancetaylor ianlancetaylor commented Jan 28, 2022

SIGCHLD only happens on Unix systems. The Unix sigtramp does correctly handle getg returning nil.

I don't know enough about Windows exceptions off-hand to know whether the same problem occurs. It wouldn't be surprising. The windows-amd64 sigtramp function does appear to handle a nil g.

Copy link

@marler8997 marler8997 commented Jan 28, 2022

Yes the same problem occurs on Windows. On windows rather than signals they call this "Vectored Exception Handling". It's a simple mechanism where the applications can register multiple callbacks which are then called by whatever mechanism Windows uses to capture interrupts and propagate them to userspace. The handler will continue to call each one or stop depending on the return value of the previous call.

What's happening in our case is another library is using exception handling as normal control flow. When the exception occurs it calls go's sigtramp on a thread that go's runtime doesn't know about and viola, here we are.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
arch-arm64 NeedsInvestigation OS-Windows
None yet

No branches or pull requests

4 participants