-
Notifications
You must be signed in to change notification settings - Fork 18k
runtime: "fatal error: unexpected signal" 0xC0000005 on Windows for a small program with a large allocation #37470
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
Comments
The |
This isn't the stack growth itself causing the crash, but when we try to unroll a temporary GC program for scanning the large stack-allocated object. I'm not sure what's happening exactly, but that's just a bug. That should never crash. |
@ulikunitz, do you know if this is reproducible with Go 1.13? |
Found it. In this case, the GC bitmap for |
I'm not sure how this could lead to |
Change https://golang.org/cl/221197 mentions this issue: |
@gopherbot, please open a backport to Go 1.14 and Go 1.15. |
Backport issue(s) opened: #37480 (for 1.14), #37481 (for 1.15). Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://golang.org/wiki/MinorReleases. |
Oops. @gopherbot, please open a backport to Go 1.13. |
Also needs 1.12 backport? There's a queue of fixes for the final 1.12.x release: gopherbot can't backport more than once per issue. cc @dmitshur |
@networkimprov, now that 1.14 has been released I would not expect any further 1.12.x releases. |
I checked that 1.13 and 1.13.2 works and first broken version appears to be 1.13.3. So 1.12 is probably not affected. |
No, go1.12.9 is also broken. It shares probably a CL with the go1.13 release branch |
Manually opened #37483 for Go 1.13. |
Here is the report of what I tested under Windows.
|
Yes, this bug was introduced in https://go-review.googlesource.com/c/134155 as part of adding support for stack objects, which was released in Go 1.12. Though, as @bcmills pointed out, we're probably not going to do any more 1.12 releases. The crash is very sensitive to the behavior of the memory allocator, so the fact that it didn't reproduce on 1.13 or 1.13.2 doesn't indicate much. The problem has been there since that CL was committed. |
Many thanks for the explanation and the fix. Meanwhile I tested https://golang.org/cl/221197 on Linux and Windows and can happily report that i was not able to reproduce any of the issues with the package on Linux and WIndows. |
@aclements You've asked for this issue to be backported to Go 1.14 and 1.13. This seems like a serious issue, do you think there is a workaround that can be used? |
@dmitshur, technically a workaround could be to pad all types of size [N524288+1, N524288+63] for any integer N so they're not that size any more. That's both really awful (and can apply to code you depend on but don't control), and you have to know that you've encountered this issue to even think about doing something like that, which is most likely to just show up as memory corruption, which you might not even notice. So, practically speaking, I'd say there isn't really a workaround. |
Hi, Apparently the CL https://golang.org/cl/221197 didn't make it into 1.14.1. #37480 has been moved to milestone go1.14.2. I guess because the CL review has not been completed. Is there anything I can do to move the CL forward? |
@ulikunitz Yes, the review needs to be completed. The CL will then get submitted, backported, and be a part of the next minor release. I've left a ping for @aclements on the CL in case the notification fell through. |
Oof, sorry this missed 1.14.1. Things have been crazy. I've updated the CL. |
No problem Austin, it'll make its way into the next minor release. Thank you! |
Change https://golang.org/cl/224417 mentions this issue: |
Change https://golang.org/cl/224418 mentions this issue: |
materializeGCProg allocates a temporary buffer for unrolling a GC program. Unfortunately, when computing the size of the buffer, it rounds *down* the number of bytes needed to store bitmap before rounding up the number of pages needed to store those bytes. The fact that it rounds up to pages usually mitigates the rounding down, but the type from #37470 exists right on the boundary where this doesn't work: type Sequencer struct { htable [1 << 17]uint32 buf []byte } On 64-bit, this GC bitmap is exactly 8 KiB of zeros, followed by three one bits. Hence, this needs 8193 bytes of storage, but the current math in materializeGCProg rounds *down* the three one bits to 8192 bytes. Since this is exactly pageSize, the next step of rounding up to the page size doesn't mitigate this error, and materializeGCProg allocates a buffer that is one byte too small. runGCProg then writes one byte past the end of this buffer, causing either a segfault (if you're lucky!) or memory corruption. Updates #37470. Fixes #37480. Change-Id: Iad24c463c501cd9b1dc1924bc2ad007991a094a0 Reviewed-on: https://go-review.googlesource.com/c/go/+/224417 Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
materializeGCProg allocates a temporary buffer for unrolling a GC program. Unfortunately, when computing the size of the buffer, it rounds *down* the number of bytes needed to store bitmap before rounding up the number of pages needed to store those bytes. The fact that it rounds up to pages usually mitigates the rounding down, but the type from #37470 exists right on the boundary where this doesn't work: type Sequencer struct { htable [1 << 17]uint32 buf []byte } On 64-bit, this GC bitmap is exactly 8 KiB of zeros, followed by three one bits. Hence, this needs 8193 bytes of storage, but the current math in materializeGCProg rounds *down* the three one bits to 8192 bytes. Since this is exactly pageSize, the next step of rounding up to the page size doesn't mitigate this error, and materializeGCProg allocates a buffer that is one byte too small. runGCProg then writes one byte past the end of this buffer, causing either a segfault (if you're lucky!) or memory corruption. Updates #37470. Fixes #37483. Change-Id: Iad24c463c501cd9b1dc1924bc2ad007991a094a0 Reviewed-on: https://go-review.googlesource.com/c/go/+/224418 Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
The tests were run with Go 1.14 on a fully patched Windows 10 Home Version 1909 (Build 18363.657).
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
I'm developing a package that creates Lempel-Ziv sequences for byte streams. On my usual development environment Ubuntu 18.04 I observe sometimes crashes of the test runs (
fatal error: bad g->status in ready
) for go1.13.8 and go1.14 on multiple kernels including 4.15.0 and 5.3.18. Both should not be affected by the AVX register corruption.To exclude Linux as a factor I tested the package on Windows and got a fatal error on every run. I was able to reduce it to a small program. The program runs without any errors on Linux. Whether the Windows issue is related to the Linux problems I cannot tell. I'm aware that initializing a structure with a huge array this way is not a good idea, but that is what I wrote initially and what appears to trigger the stack extension that runs into an invalid address access.
I started the program with go run.
https://play.golang.org/p/VRavJw-WPie
What did you expect to see?
No output and no fatal error.
What did you see instead?
The text was updated successfully, but these errors were encountered: