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

Delta Between Two Patch Sets: src/runtime/stack_test.go

Issue 141490043: code review 141490043: runtime: use traceback to traverse defer structures (Closed)
Left Patch Set: Created 9 years, 6 months ago
Right Patch Set: diff -r 86735ca806e08b2ee073776fdddd0f7712dd788a https://code.google.com/p/go/ Created 9 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « src/runtime/stack.c ('k') | src/runtime/traceback.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2012 The Go Authors. All rights reserved. 1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package runtime_test 5 package runtime_test
6 6
7 import ( 7 import (
8 . "runtime" 8 . "runtime"
9 "strings" 9 "strings"
10 "sync" 10 "sync"
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 for i := 0; i < n; i++ { 134 for i := 0; i < n; i++ {
135 x := 0 135 x := 0
136 growStackIter(&x, i) 136 growStackIter(&x, i)
137 if x != i+1 { 137 if x != i+1 {
138 panic("stack is corrupted") 138 panic("stack is corrupted")
139 } 139 }
140 } 140 }
141 GC() 141 GC()
142 } 142 }
143 143
144 // This function is not an anonimous func, so that the compiler can do escape 144 // This function is not an anonymous func, so that the compiler can do escape
145 // analysis and place x on stack (and subsequently stack growth update the point er). 145 // analysis and place x on stack (and subsequently stack growth update the point er).
146 func growStackIter(p *int, n int) { 146 func growStackIter(p *int, n int) {
147 if n == 0 { 147 if n == 0 {
148 *p = n + 1 148 *p = n + 1
149 GC() 149 GC()
150 return 150 return
151 } 151 }
152 *p = n + 1 152 *p = n + 1
153 x := 0 153 x := 0
154 growStackIter(&x, n-1) 154 growStackIter(&x, n-1)
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 223
224 defer func() { 224 defer func() {
225 if y != 42 { 225 if y != 42 {
226 t.Errorf("defer's stack references were not adjusted app ropriately") 226 t.Errorf("defer's stack references were not adjusted app ropriately")
227 } 227 }
228 }() 228 }()
229 defer set(&y, 42) 229 defer set(&y, 42)
230 growStack() 230 growStack()
231 } 231 }
232 232
233 // use about n KB of stack 233 type bigBuf [4 * 1024]byte
234
235 // TestDeferPtrsGoexit is like TestDeferPtrs but exercises the possibility that the
236 // stack grows as part of starting the deferred function. It calls Goexit at var ious
237 // stack depths, forcing the deferred function (with >4kB of args) to be run at
238 // the bottom of the stack. The goal is to find a stack depth less than 4kB from
239 // the end of the stack. Each trial runs in a different goroutine so that an ear lier
240 // stack growth does not invalidate a later attempt.
241 func TestDeferPtrsGoexit(t *testing.T) {
242 » for i := 0; i < 100; i++ {
243 » » c := make(chan int, 1)
244 » » go testDeferPtrsGoexit(c, i)
245 » » if n := <-c; n != 42 {
246 » » » t.Fatalf("defer's stack references were not adjusted app ropriately (i=%d n=%d)", i, n)
247 » » }
248 » }
249 }
250
251 func testDeferPtrsGoexit(c chan int, i int) {
252 » var y int
253 » defer func() {
254 » » c <- y
255 » }()
256 » defer setBig(&y, 42, bigBuf{})
257 » useStackAndCall(i, Goexit)
258 }
259
260 func setBig(p *int, x int, b bigBuf) {
261 » *p = x
262 }
263
264 // TestDeferPtrsPanic is like TestDeferPtrsGoexit, but it's using panic instead
265 // of Goexit to run the Defers. Those two are different execution paths
266 // in the runtime.
267 func TestDeferPtrsPanic(t *testing.T) {
268 » for i := 0; i < 100; i++ {
269 » » c := make(chan int, 1)
270 » » go testDeferPtrsGoexit(c, i)
271 » » if n := <-c; n != 42 {
272 » » » t.Fatalf("defer's stack references were not adjusted app ropriately (i=%d n=%d)", i, n)
273 » » }
274 » }
275 }
276
277 func testDeferPtrsPanic(c chan int, i int) {
278 » var y int
279 » defer func() {
280 » » if recover() == nil {
281 » » » c <- -1
282 » » » return
283 » » }
284 » » c <- y
285 » }()
286 » defer setBig(&y, 42, bigBuf{})
287 » useStackAndCall(i, func() { panic(1) })
288 }
289
290 // TestPanicUseStack checks that a chain of Panic structs on the stack are
291 // updated correctly if the stack grows during the deferred execution that
292 // happens as a result of the panic.
293 func TestPanicUseStack(t *testing.T) {
294 » pc := make([]uintptr, 10000)
295 » defer func() {
296 » » recover()
297 » » Callers(0, pc) // force stack walk
298 » » useStackAndCall(100, func() {
299 » » » defer func() {
300 » » » » recover()
301 » » » » Callers(0, pc) // force stack walk
302 » » » » useStackAndCall(200, func() {
303 » » » » » defer func() {
304 » » » » » » recover()
305 » » » » » » Callers(0, pc) // force stack wa lk
306 » » » » » }()
307 » » » » » panic(3)
308 » » » » })
309 » » » }()
310 » » » panic(2)
311 » » })
312 » }()
313 » panic(1)
314 }
315
316 // use about n KB of stack and call f
317 func useStackAndCall(n int, f func()) {
318 » if n == 0 {
319 » » f()
320 » » return
321 » }
322 » var b [1024]byte // makes frame about 1KB
323 » useStackAndCall(n-1+int(b[99]), f)
324 }
325
234 func useStack(n int) { 326 func useStack(n int) {
235 » if n == 0 { 327 » useStackAndCall(n, func() {})
236 » » return
237 » }
238 » var b [1024]byte // makes frame about 1KB
239 » useStack(n - 1 + int(b[99]))
240 } 328 }
241 329
242 func growing(c chan int, done chan struct{}) { 330 func growing(c chan int, done chan struct{}) {
243 for n := range c { 331 for n := range c {
244 useStack(n) 332 useStack(n)
245 done <- struct{}{} 333 done <- struct{}{}
246 } 334 }
247 done <- struct{}{} 335 done <- struct{}{}
248 } 336 }
249 337
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 // To make this test effective, edit panic.go:gopanic and uncomment 392 // To make this test effective, edit panic.go:gopanic and uncomment
305 // the GC() call just before freedefer(d). 393 // the GC() call just before freedefer(d).
306 defer func() { 394 defer func() {
307 if x := recover(); x == nil { 395 if x := recover(); x == nil {
308 t.Errorf("recover failed") 396 t.Errorf("recover failed")
309 } 397 }
310 }() 398 }()
311 useStack(32) 399 useStack(32)
312 panic("test panic") 400 panic("test panic")
313 } 401 }
LEFTRIGHT

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