github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/panic.c (about)

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