~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/runtime/panic.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012 The Go Authors. All rights reserved.
 
2
// Use of this source code is governed by a BSD-style
 
3
// license that can be found in the LICENSE file.
 
4
 
 
5
#include "runtime.h"
 
6
#include "arch_GOARCH.h"
 
7
#include "stack.h"
 
8
#include "malloc.h"
 
9
 
 
10
// Code related to defer, panic and recover.
 
11
 
 
12
uint32 runtime·panicking;
 
13
static Lock paniclk;
 
14
 
 
15
enum
 
16
{
 
17
        DeferChunkSize = 2048
 
18
};
 
19
 
 
20
// Allocate a Defer, usually as part of the larger frame of deferred functions.
 
21
// Each defer must be released with both popdefer and freedefer.
 
22
static Defer*
 
23
newdefer(int32 siz)
 
24
{
 
25
        int32 total;
 
26
        DeferChunk *c;
 
27
        Defer *d;
 
28
        
 
29
        c = g->dchunk;
 
30
        total = sizeof(*d) + ROUND(siz, sizeof(uintptr)) - sizeof(d->args);
 
31
        if(c == nil || total > DeferChunkSize - c->off) {
 
32
                if(total > DeferChunkSize / 2) {
 
33
                        // Not worth putting in any chunk.
 
34
                        // Allocate a separate block.
 
35
                        d = runtime·malloc(total);
 
36
                        d->siz = siz;
 
37
                        d->special = 1;
 
38
                        d->free = 1;
 
39
                        d->link = g->defer;
 
40
                        g->defer = d;
 
41
                        return d;
 
42
                }
 
43
 
 
44
                // Cannot fit in current chunk.
 
45
                // Switch to next chunk, allocating if necessary.
 
46
                c = g->dchunknext;
 
47
                if(c == nil)
 
48
                        c = runtime·malloc(DeferChunkSize);
 
49
                c->prev = g->dchunk;
 
50
                c->off = sizeof(*c);
 
51
                g->dchunk = c;
 
52
                g->dchunknext = nil;
 
53
        }
 
54
 
 
55
        d = (Defer*)((byte*)c + c->off);
 
56
        c->off += total;
 
57
        d->siz = siz;
 
58
        d->special = 0;
 
59
        d->free = 0;
 
60
        d->link = g->defer;
 
61
        g->defer = d;
 
62
        return d;       
 
63
}
 
64
 
 
65
// Pop the current defer from the defer stack.
 
66
// Its contents are still valid until the goroutine begins executing again.
 
67
// In particular it is safe to call reflect.call(d->fn, d->argp, d->siz) after
 
68
// popdefer returns.
 
69
static void
 
70
popdefer(void)
 
71
{
 
72
        Defer *d;
 
73
        DeferChunk *c;
 
74
        int32 total;
 
75
        
 
76
        d = g->defer;
 
77
        if(d == nil)
 
78
                runtime·throw("runtime: popdefer nil");
 
79
        g->defer = d->link;
 
80
        if(d->special) {
 
81
                // Nothing else to do.
 
82
                return;
 
83
        }
 
84
        total = sizeof(*d) + ROUND(d->siz, sizeof(uintptr)) - sizeof(d->args);
 
85
        c = g->dchunk;
 
86
        if(c == nil || (byte*)d+total != (byte*)c+c->off)
 
87
                runtime·throw("runtime: popdefer phase error");
 
88
        c->off -= total;
 
89
        if(c->off == sizeof(*c)) {
 
90
                // Chunk now empty, so pop from stack.
 
91
                // Save in dchunknext both to help with pingponging between frames
 
92
                // and to make sure d is still valid on return.
 
93
                if(g->dchunknext != nil)
 
94
                        runtime·free(g->dchunknext);
 
95
                g->dchunknext = c;
 
96
                g->dchunk = c->prev;
 
97
        }
 
98
}
 
99
 
 
100
// Free the given defer.
 
101
// For defers in the per-goroutine chunk this just clears the saved arguments.
 
102
// For large defers allocated on the heap, this frees them.
 
103
// The defer cannot be used after this call.
 
104
static void
 
105
freedefer(Defer *d)
 
106
{
 
107
        if(d->special) {
 
108
                if(d->free)
 
109
                        runtime·free(d);
 
110
        } else {
 
111
                runtime·memclr((byte*)d->args, d->siz);
 
112
        }
 
113
}
 
114
 
 
115
// Create a new deferred function fn with siz bytes of arguments.
 
116
// The compiler turns a defer statement into a call to this.
 
117
// Cannot split the stack because it assumes that the arguments
 
118
// are available sequentially after &fn; they would not be
 
119
// copied if a stack split occurred.  It's OK for this to call
 
120
// functions that split the stack.
 
121
#pragma textflag 7
 
122
uintptr
 
123
runtime·deferproc(int32 siz, FuncVal *fn, ...)
 
124
{
 
125
        Defer *d;
 
126
 
 
127
        d = newdefer(siz);
 
128
        d->fn = fn;
 
129
        d->pc = runtime·getcallerpc(&siz);
 
130
        if(thechar == '5')
 
131
                d->argp = (byte*)(&fn+2);  // skip caller's saved link register
 
132
        else
 
133
                d->argp = (byte*)(&fn+1);
 
134
        runtime·memmove(d->args, d->argp, d->siz);
 
135
 
 
136
        // deferproc returns 0 normally.
 
137
        // a deferred func that stops a panic
 
138
        // makes the deferproc return 1.
 
139
        // the code the compiler generates always
 
140
        // checks the return value and jumps to the
 
141
        // end of the function if deferproc returns != 0.
 
142
        return 0;
 
143
}
 
144
 
 
145
// Run a deferred function if there is one.
 
146
// The compiler inserts a call to this at the end of any
 
147
// function which calls defer.
 
148
// If there is a deferred function, this will call runtime·jmpdefer,
 
149
// which will jump to the deferred function such that it appears
 
150
// to have been called by the caller of deferreturn at the point
 
151
// just before deferreturn was called.  The effect is that deferreturn
 
152
// is called again and again until there are no more deferred functions.
 
153
// Cannot split the stack because we reuse the caller's frame to
 
154
// call the deferred function.
 
155
#pragma textflag 7
 
156
void
 
157
runtime·deferreturn(uintptr arg0)
 
158
{
 
159
        Defer *d;
 
160
        byte *argp;
 
161
        FuncVal *fn;
 
162
 
 
163
        d = g->defer;
 
164
        if(d == nil)
 
165
                return;
 
166
        argp = (byte*)&arg0;
 
167
        if(d->argp != argp)
 
168
                return;
 
169
        runtime·memmove(argp, d->args, d->siz);
 
170
        fn = d->fn;
 
171
        popdefer();
 
172
        freedefer(d);
 
173
        runtime·jmpdefer(fn, argp);
 
174
}
 
175
 
 
176
// Run all deferred functions for the current goroutine.
 
177
static void
 
178
rundefer(void)
 
179
{
 
180
        Defer *d;
 
181
 
 
182
        while((d = g->defer) != nil) {
 
183
                popdefer();
 
184
                reflect·call(d->fn, (byte*)d->args, d->siz);
 
185
                freedefer(d);
 
186
        }
 
187
}
 
188
 
 
189
// Print all currently active panics.  Used when crashing.
 
190
static void
 
191
printpanics(Panic *p)
 
192
{
 
193
        if(p->link) {
 
194
                printpanics(p->link);
 
195
                runtime·printf("\t");
 
196
        }
 
197
        runtime·printf("panic: ");
 
198
        runtime·printany(p->arg);
 
199
        if(p->recovered)
 
200
                runtime·printf(" [recovered]");
 
201
        runtime·printf("\n");
 
202
}
 
203
 
 
204
static void recovery(G*);
 
205
 
 
206
// The implementation of the predeclared function panic.
 
207
void
 
208
runtime·panic(Eface e)
 
209
{
 
210
        Defer *d;
 
211
        Panic *p;
 
212
        void *pc, *argp;
 
213
        
 
214
        p = runtime·mal(sizeof *p);
 
215
        p->arg = e;
 
216
        p->link = g->panic;
 
217
        p->stackbase = (byte*)g->stackbase;
 
218
        g->panic = p;
 
219
 
 
220
        for(;;) {
 
221
                d = g->defer;
 
222
                if(d == nil)
 
223
                        break;
 
224
                // take defer off list in case of recursive panic
 
225
                popdefer();
 
226
                g->ispanic = true;      // rock for newstack, where reflect.call ends up
 
227
                argp = d->argp;
 
228
                pc = d->pc;
 
229
                reflect·call(d->fn, (byte*)d->args, d->siz);
 
230
                freedefer(d);
 
231
                if(p->recovered) {
 
232
                        g->panic = p->link;
 
233
                        if(g->panic == nil)     // must be done with signal
 
234
                                g->sig = 0;
 
235
                        runtime·free(p);
 
236
                        // Pass information about recovering frame to recovery.
 
237
                        g->sigcode0 = (uintptr)argp;
 
238
                        g->sigcode1 = (uintptr)pc;
 
239
                        runtime·mcall(recovery);
 
240
                        runtime·throw("recovery failed"); // mcall should not return
 
241
                }
 
242
        }
 
243
 
 
244
        // ran out of deferred calls - old-school panic now
 
245
        runtime·startpanic();
 
246
        printpanics(g->panic);
 
247
        runtime·dopanic(0);
 
248
}
 
249
 
 
250
// Unwind the stack after a deferred function calls recover
 
251
// after a panic.  Then arrange to continue running as though
 
252
// the caller of the deferred function returned normally.
 
253
static void
 
254
recovery(G *gp)
 
255
{
 
256
        void *argp;
 
257
        void *pc;
 
258
        
 
259
        // Info about defer passed in G struct.
 
260
        argp = (void*)gp->sigcode0;
 
261
        pc = (void*)gp->sigcode1;
 
262
 
 
263
        // Unwind to the stack frame with d's arguments in it.
 
264
        runtime·unwindstack(gp, argp);
 
265
 
 
266
        // Make the deferproc for this d return again,
 
267
        // this time returning 1.  The calling function will
 
268
        // jump to the standard return epilogue.
 
269
        // The -2*sizeof(uintptr) makes up for the
 
270
        // two extra words that are on the stack at
 
271
        // each call to deferproc.
 
272
        // (The pc we're returning to does pop pop
 
273
        // before it tests the return value.)
 
274
        // On the arm there are 2 saved LRs mixed in too.
 
275
        if(thechar == '5')
 
276
                gp->sched.sp = (uintptr)argp - 4*sizeof(uintptr);
 
277
        else
 
278
                gp->sched.sp = (uintptr)argp - 2*sizeof(uintptr);
 
279
        gp->sched.pc = pc;
 
280
        runtime·gogo(&gp->sched, 1);
 
281
}
 
282
 
 
283
// Free stack frames until we hit the last one
 
284
// or until we find the one that contains the sp.
 
285
void
 
286
runtime·unwindstack(G *gp, byte *sp)
 
287
{
 
288
        Stktop *top;
 
289
        byte *stk;
 
290
 
 
291
        // Must be called from a different goroutine, usually m->g0.
 
292
        if(g == gp)
 
293
                runtime·throw("unwindstack on self");
 
294
 
 
295
        while((top = (Stktop*)gp->stackbase) != nil && top->stackbase != nil) {
 
296
                stk = (byte*)gp->stackguard - StackGuard;
 
297
                if(stk <= sp && sp < (byte*)gp->stackbase)
 
298
                        break;
 
299
                gp->stackbase = (uintptr)top->stackbase;
 
300
                gp->stackguard = (uintptr)top->stackguard;
 
301
                if(top->free != 0)
 
302
                        runtime·stackfree(stk, top->free);
 
303
        }
 
304
 
 
305
        if(sp != nil && (sp < (byte*)gp->stackguard - StackGuard || (byte*)gp->stackbase < sp)) {
 
306
                runtime·printf("recover: %p not in [%p, %p]\n", sp, gp->stackguard - StackGuard, gp->stackbase);
 
307
                runtime·throw("bad unwindstack");
 
308
        }
 
309
}
 
310
 
 
311
// The implementation of the predeclared function recover.
 
312
// Cannot split the stack because it needs to reliably
 
313
// find the stack segment of its caller.
 
314
#pragma textflag 7
 
315
void
 
316
runtime·recover(byte *argp, Eface ret)
 
317
{
 
318
        Stktop *top, *oldtop;
 
319
        Panic *p;
 
320
 
 
321
        // Must be a panic going on.
 
322
        if((p = g->panic) == nil || p->recovered)
 
323
                goto nomatch;
 
324
 
 
325
        // Frame must be at the top of the stack segment,
 
326
        // because each deferred call starts a new stack
 
327
        // segment as a side effect of using reflect.call.
 
328
        // (There has to be some way to remember the
 
329
        // variable argument frame size, and the segment
 
330
        // code already takes care of that for us, so we
 
331
        // reuse it.)
 
332
        //
 
333
        // As usual closures complicate things: the fp that
 
334
        // the closure implementation function claims to have
 
335
        // is where the explicit arguments start, after the
 
336
        // implicit pointer arguments and PC slot.
 
337
        // If we're on the first new segment for a closure,
 
338
        // then fp == top - top->args is correct, but if
 
339
        // the closure has its own big argument frame and
 
340
        // allocated a second segment (see below),
 
341
        // the fp is slightly above top - top->args.
 
342
        // That condition can't happen normally though
 
343
        // (stack pointers go down, not up), so we can accept
 
344
        // any fp between top and top - top->args as
 
345
        // indicating the top of the segment.
 
346
        top = (Stktop*)g->stackbase;
 
347
        if(argp < (byte*)top - top->argsize || (byte*)top < argp)
 
348
                goto nomatch;
 
349
 
 
350
        // The deferred call makes a new segment big enough
 
351
        // for the argument frame but not necessarily big
 
352
        // enough for the function's local frame (size unknown
 
353
        // at the time of the call), so the function might have
 
354
        // made its own segment immediately.  If that's the
 
355
        // case, back top up to the older one, the one that
 
356
        // reflect.call would have made for the panic.
 
357
        //
 
358
        // The fp comparison here checks that the argument
 
359
        // frame that was copied during the split (the top->args
 
360
        // bytes above top->fp) abuts the old top of stack.
 
361
        // This is a correct test for both closure and non-closure code.
 
362
        oldtop = (Stktop*)top->stackbase;
 
363
        if(oldtop != nil && top->argp == (byte*)oldtop - top->argsize)
 
364
                top = oldtop;
 
365
 
 
366
        // Now we have the segment that was created to
 
367
        // run this call.  It must have been marked as a panic segment.
 
368
        if(!top->panic)
 
369
                goto nomatch;
 
370
 
 
371
        // Okay, this is the top frame of a deferred call
 
372
        // in response to a panic.  It can see the panic argument.
 
373
        p->recovered = 1;
 
374
        ret = p->arg;
 
375
        FLUSH(&ret);
 
376
        return;
 
377
 
 
378
nomatch:
 
379
        ret.type = nil;
 
380
        ret.data = nil;
 
381
        FLUSH(&ret);
 
382
}
 
383
 
 
384
void
 
385
runtime·startpanic(void)
 
386
{
 
387
        if(runtime·mheap == 0 || runtime·mheap->cachealloc.size == 0) { // very early
 
388
                runtime·printf("runtime: panic before malloc heap initialized\n");
 
389
                m->mallocing = 1; // tell rest of panic not to try to malloc
 
390
        } else if(m->mcache == nil) // can happen if called from signal handler or throw
 
391
                m->mcache = runtime·allocmcache();
 
392
        if(m->dying) {
 
393
                runtime·printf("panic during panic\n");
 
394
                runtime·exit(3);
 
395
        }
 
396
        m->dying = 1;
 
397
        runtime·xadd(&runtime·panicking, 1);
 
398
        runtime·lock(&paniclk);
 
399
}
 
400
 
 
401
void
 
402
runtime·dopanic(int32 unused)
 
403
{
 
404
        static bool didothers;
 
405
        bool crash;
 
406
 
 
407
        if(g->sig != 0)
 
408
                runtime·printf("[signal %x code=%p addr=%p pc=%p]\n",
 
409
                        g->sig, g->sigcode0, g->sigcode1, g->sigpc);
 
410
 
 
411
        if(runtime·gotraceback(&crash)){
 
412
                if(g != m->g0) {
 
413
                        runtime·printf("\n");
 
414
                        runtime·goroutineheader(g);
 
415
                        runtime·traceback(runtime·getcallerpc(&unused), runtime·getcallersp(&unused), 0, g);
 
416
                }
 
417
                if(!didothers) {
 
418
                        didothers = true;
 
419
                        runtime·tracebackothers(g);
 
420
                }
 
421
        }
 
422
        runtime·unlock(&paniclk);
 
423
        if(runtime·xadd(&runtime·panicking, -1) != 0) {
 
424
                // Some other m is panicking too.
 
425
                // Let it print what it needs to print.
 
426
                // Wait forever without chewing up cpu.
 
427
                // It will exit when it's done.
 
428
                static Lock deadlock;
 
429
                runtime·lock(&deadlock);
 
430
                runtime·lock(&deadlock);
 
431
        }
 
432
        
 
433
        if(crash)
 
434
                runtime·crash();
 
435
 
 
436
        runtime·exit(2);
 
437
}
 
438
 
 
439
void
 
440
runtime·panicindex(void)
 
441
{
 
442
        runtime·panicstring("index out of range");
 
443
}
 
444
 
 
445
void
 
446
runtime·panicslice(void)
 
447
{
 
448
        runtime·panicstring("slice bounds out of range");
 
449
}
 
450
 
 
451
void
 
452
runtime·throwreturn(void)
 
453
{
 
454
        // can only happen if compiler is broken
 
455
        runtime·throw("no return at end of a typed function - compiler is broken");
 
456
}
 
457
 
 
458
void
 
459
runtime·throwinit(void)
 
460
{
 
461
        // can only happen with linker skew
 
462
        runtime·throw("recursive call during initialization - linker skew");
 
463
}
 
464
 
 
465
void
 
466
runtime·throw(int8 *s)
 
467
{
 
468
        if(m->throwing == 0)
 
469
                m->throwing = 1;
 
470
        runtime·startpanic();
 
471
        runtime·printf("fatal error: %s\n", s);
 
472
        runtime·dopanic(0);
 
473
        *(int32*)0 = 0; // not reached
 
474
        runtime·exit(1);        // even more not reached
 
475
}
 
476
 
 
477
void
 
478
runtime·panicstring(int8 *s)
 
479
{
 
480
        Eface err;
 
481
 
 
482
        if(m->gcing) {
 
483
                runtime·printf("panic: %s\n", s);
 
484
                runtime·throw("panic during gc");
 
485
        }
 
486
        runtime·newErrorString(runtime·gostringnocopy((byte*)s), &err);
 
487
        runtime·panic(err);
 
488
}
 
489
 
 
490
void
 
491
runtime·Goexit(void)
 
492
{
 
493
        rundefer();
 
494
        runtime·goexit();
 
495
}