Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(23)

Issue 141490043: code review 141490043: runtime: use traceback to traverse defer structures (Closed)

Can't Edit
Can't Publish+Mail
Start Review
Created:
7 years, 2 months ago by rsc
Modified:
7 years, 2 months ago
Reviewers:
khr
CC:
khr, dvyukov, golang-codereviews, iant, rlh
Visibility:
Public.

Description

runtime: use traceback to traverse defer structures This makes the GC and the stack copying agree about how to interpret the defer structures. Previously, only the stack copying treated them precisely. This removes an untyped memory allocation and fixes at least three copystack bugs. To make sure the GC can find the deferred argument frame until it has been copied, keep a Defer on the defer list during its execution. In addition to making it possible to remove the untyped memory allocation, keeping the Defer on the list fixes two races between copystack and execution of defers (in both gopanic and Goexit). The problem is that once the defer has been taken off the list, a stack copy that happens before the deferred arguments have been copied back to the stack will not update the arguments correctly. The new tests TestDeferPtrsPanic and TestDeferPtrsGoexit (variations on the existing TestDeferPtrs) pass now but failed before this CL. In addition to those fixes, keeping the Defer on the list helps correct a dangling pointer error during copystack. The traceback routines walk the Defer chain to provide information about where a panic may resume execution. When the executing Defer was not on the Defer chain but instead linked from the Panic chain, the traceback had to walk the Panic chain too. But Panic structs are on the stack and being updated by copystack. Traceback's use of the Panic chain while copystack is updating those structs means that it can follow an updated pointer and find itself reading from the new stack. The new stack is usually all zeros, so it sees an incorrect early end to the chain. The new TestPanicUseStack makes this happen at tip and dies when adjustdefers finds an unexpected argp. The new StackCopyPoison mode causes an earlier bad dereference instead. By keeping the Defer on the list, traceback can avoid walking the Panic chain at all, making it okay for copystack to update the Panics. We'd have the same problem for any Defers on the stack. There was only one: gopanic's dabort. Since we are not taking the executing Defer off the chain, we can use it to do what dabort was doing, and then there are no Defers on the stack ever, so it is okay for traceback to use the Defer chain even while copystack is executing: copystack cannot modify the Defer chain.

Patch Set 1 #

Patch Set 2 : diff -r c655137b930c3f839cc08f01f759ac5eb35d766f https://code.google.com/p/go/ #

Patch Set 3 : diff -r c655137b930c3f839cc08f01f759ac5eb35d766f https://code.google.com/p/go/ #

Patch Set 4 : diff -r c655137b930c3f839cc08f01f759ac5eb35d766f https://code.google.com/p/go/ #

Patch Set 5 : diff -r c655137b930c3f839cc08f01f759ac5eb35d766f https://code.google.com/p/go/ #

Total comments: 6

Patch Set 6 : diff -r 86735ca806e08b2ee073776fdddd0f7712dd788a https://code.google.com/p/go/ #

Unified diffs Side-by-side diffs Delta from patch set Stats (+298 lines, -175 lines) Patch
M src/runtime/heapdump.c View 1 2 3 1 chunk +1 line, -1 line 0 comments Download
M src/runtime/malloc.go View 1 2 3 4 5 1 chunk +10 lines, -0 lines 0 comments Download
M src/runtime/mgc0.c View 1 2 3 4 5 1 chunk +1 line, -0 lines 0 comments Download
M src/runtime/panic.c View 1 2 2 chunks +3 lines, -2 lines 0 comments Download
M src/runtime/panic.go View 1 2 3 4 5 8 chunks +65 lines, -43 lines 0 comments Download
M src/runtime/proc.go View 1 2 3 2 chunks +6 lines, -5 lines 0 comments Download
M src/runtime/runtime.h View 1 2 3 4 5 2 chunks +2 lines, -3 lines 0 comments Download
M src/runtime/stack.c View 1 2 3 4 5 9 chunks +62 lines, -74 lines 0 comments Download
M src/runtime/stack_test.go View 1 2 3 4 2 chunks +92 lines, -4 lines 0 comments Download
M src/runtime/traceback.go View 1 2 5 chunks +56 lines, -43 lines 0 comments Download

Messages

Total messages: 4
rsc
Hello khr (cc: dvyukov, golang-codereviews@googlegroups.com, iant, rlh), I'd like you to review this change to ...
7 years, 2 months ago (2014-09-12 20:01:42 UTC) #1
khr
LGTM. https://codereview.appspot.com/141490043/diff/80001/src/runtime/panic.go File src/runtime/panic.go (right): https://codereview.appspot.com/141490043/diff/80001/src/runtime/panic.go#newcode147 src/runtime/panic.go:147: func deferArgs(d *_defer) unsafe.Pointer { Mark this as ...
7 years, 2 months ago (2014-09-15 19:23:00 UTC) #2
rsc
https://codereview.appspot.com/141490043/diff/80001/src/runtime/panic.go File src/runtime/panic.go (right): https://codereview.appspot.com/141490043/diff/80001/src/runtime/panic.go#newcode147 src/runtime/panic.go:147: func deferArgs(d *_defer) unsafe.Pointer { On 2014/09/15 19:23:00, khr ...
7 years, 2 months ago (2014-09-16 14:28:37 UTC) #3
rsc
7 years, 2 months ago (2014-09-16 14:36:43 UTC) #4
*** Submitted as https://code.google.com/p/go/source/detail?r=fc469a8e7add ***

runtime: use traceback to traverse defer structures

This makes the GC and the stack copying agree about how
to interpret the defer structures. Previously, only the stack
copying treated them precisely.
This removes an untyped memory allocation and fixes
at least three copystack bugs.

To make sure the GC can find the deferred argument
frame until it has been copied, keep a Defer on the defer list
during its execution.

In addition to making it possible to remove the untyped
memory allocation, keeping the Defer on the list fixes
two races between copystack and execution of defers
(in both gopanic and Goexit). The problem is that once
the defer has been taken off the list, a stack copy that
happens before the deferred arguments have been copied
back to the stack will not update the arguments correctly.
The new tests TestDeferPtrsPanic and TestDeferPtrsGoexit
(variations on the existing TestDeferPtrs) pass now but
failed before this CL.

In addition to those fixes, keeping the Defer on the list
helps correct a dangling pointer error during copystack.
The traceback routines walk the Defer chain to provide
information about where a panic may resume execution.
When the executing Defer was not on the Defer chain
but instead linked from the Panic chain, the traceback
had to walk the Panic chain too. But Panic structs are
on the stack and being updated by copystack.
Traceback's use of the Panic chain while copystack is
updating those structs means that it can follow an
updated pointer and find itself reading from the new stack.
The new stack is usually all zeros, so it sees an incorrect
early end to the chain. The new TestPanicUseStack makes
this happen at tip and dies when adjustdefers finds an
unexpected argp. The new StackCopyPoison mode
causes an earlier bad dereference instead.
By keeping the Defer on the list, traceback can avoid
walking the Panic chain at all,  making it okay for copystack
to update the Panics.

We'd have the same problem for any Defers on the stack.
There was only one: gopanic's dabort. Since we are not
taking the executing Defer off the chain, we can use it
to do what dabort was doing, and then there are no
Defers on the stack ever, so it is okay for traceback to use
the Defer chain even while copystack is executing:
copystack cannot modify the Defer chain.

LGTM=khr
R=khr
CC=dvyukov, golang-codereviews, iant, rlh
https://codereview.appspot.com/141490043
Sign in to reply to this message.

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b