Commit 76c54c11 authored by Carl Shapiro's avatar Carl Shapiro

runtime: add GODEBUG option for an electric fence like heap mode

When enabled this new debugging mode will allocate objects on
their own page and never recycle memory addresses.  This is an
essential tool to root cause a broad class of heap corruption.

R=golang-dev, dave, daniel.morsing, dvyukov, rsc, iant, cshapiro
CC=golang-dev
https://golang.org/cl/22060046
parent a5cc5bab
...@@ -24,20 +24,24 @@ percentage at run time. See http://golang.org/pkg/runtime/debug/#SetGCPercent. ...@@ -24,20 +24,24 @@ percentage at run time. See http://golang.org/pkg/runtime/debug/#SetGCPercent.
The GODEBUG variable controls debug output from the runtime. GODEBUG value is The GODEBUG variable controls debug output from the runtime. GODEBUG value is
a comma-separated list of name=val pairs. Supported names are: a comma-separated list of name=val pairs. Supported names are:
allocfreetrace: setting allocfreetrace=1 causes every allocation to be
profiled and a stack trace printed on each object's allocation and free.
efence: setting efence=1 causes the allocator to run in a mode
where each object is allocated on a unique page and addresses are
never recycled.
gctrace: setting gctrace=1 causes the garbage collector to emit a single line to standard gctrace: setting gctrace=1 causes the garbage collector to emit a single line to standard
error at each collection, summarizing the amount of memory collected and the error at each collection, summarizing the amount of memory collected and the
length of the pause. Setting gctrace=2 emits the same summary but also length of the pause. Setting gctrace=2 emits the same summary but also
repeats each collection. repeats each collection.
schedtrace: setting schedtrace=X causes the scheduler to emit a single line to standard
error every X milliseconds, summarizing the scheduler state.
scheddetail: setting schedtrace=X and scheddetail=1 causes the scheduler to emit scheddetail: setting schedtrace=X and scheddetail=1 causes the scheduler to emit
detailed multiline info every X milliseconds, describing state of the scheduler, detailed multiline info every X milliseconds, describing state of the scheduler,
processors, threads and goroutines. processors, threads and goroutines.
allocfreetrace: setting allocfreetrace=1 causes every allocation to be schedtrace: setting schedtrace=X causes the scheduler to emit a single line to standard
profiled and a stack trace printed on each object's allocation and free. error every X milliseconds, summarizing the scheduler state.
The GOMAXPROCS variable limits the number of operating system threads that The GOMAXPROCS variable limits the number of operating system threads that
can execute user-level Go code simultaneously. There is no limit to the number of threads can execute user-level Go code simultaneously. There is no limit to the number of threads
......
...@@ -58,7 +58,7 @@ runtime·mallocgc(uintptr size, uintptr typ, uint32 flag) ...@@ -58,7 +58,7 @@ runtime·mallocgc(uintptr size, uintptr typ, uint32 flag)
size += sizeof(uintptr); size += sizeof(uintptr);
c = m->mcache; c = m->mcache;
if(size <= MaxSmallSize) { if(!runtime·debug.efence && size <= MaxSmallSize) {
// Allocate from mcache free lists. // Allocate from mcache free lists.
// Inlined version of SizeToClass(). // Inlined version of SizeToClass().
if(size <= 1024-8) if(size <= 1024-8)
...@@ -196,7 +196,10 @@ runtime·free(void *v) ...@@ -196,7 +196,10 @@ runtime·free(void *v)
// they might coalesce v into other spans and change the bitmap further. // they might coalesce v into other spans and change the bitmap further.
runtime·markfreed(v, size); runtime·markfreed(v, size);
runtime·unmarkspan(v, 1<<PageShift); runtime·unmarkspan(v, 1<<PageShift);
runtime·MHeap_Free(&runtime·mheap, s, 1); if(runtime·debug.efence)
runtime·SysFree((void*)(s->start<<PageShift), size, &mstats.heap_sys);
else
runtime·MHeap_Free(&runtime·mheap, s, 1);
c->local_nlargefree++; c->local_nlargefree++;
c->local_largefree += size; c->local_largefree += size;
} else { } else {
......
...@@ -1797,7 +1797,10 @@ sweepspan(ParFor *desc, uint32 idx) ...@@ -1797,7 +1797,10 @@ sweepspan(ParFor *desc, uint32 idx)
// Free large span. // Free large span.
runtime·unmarkspan(p, 1<<PageShift); runtime·unmarkspan(p, 1<<PageShift);
*(uintptr*)p = (uintptr)0xdeaddeaddeaddeadll; // needs zeroing *(uintptr*)p = (uintptr)0xdeaddeaddeaddeadll; // needs zeroing
runtime·MHeap_Free(&runtime·mheap, s, 1); if(runtime·debug.efence)
runtime·SysFree(p, size, &mstats.gc_sys);
else
runtime·MHeap_Free(&runtime·mheap, s, 1);
c->local_nlargefree++; c->local_nlargefree++;
c->local_largefree += size; c->local_largefree += size;
} else { } else {
......
...@@ -388,6 +388,7 @@ static struct { ...@@ -388,6 +388,7 @@ static struct {
int32* value; int32* value;
} dbgvar[] = { } dbgvar[] = {
{"allocfreetrace", &runtime·debug.allocfreetrace}, {"allocfreetrace", &runtime·debug.allocfreetrace},
{"efence", &runtime·debug.efence},
{"gctrace", &runtime·debug.gctrace}, {"gctrace", &runtime·debug.gctrace},
{"scheddetail", &runtime·debug.scheddetail}, {"scheddetail", &runtime·debug.scheddetail},
{"schedtrace", &runtime·debug.schedtrace}, {"schedtrace", &runtime·debug.schedtrace},
......
...@@ -534,6 +534,7 @@ struct CgoMal ...@@ -534,6 +534,7 @@ struct CgoMal
struct DebugVars struct DebugVars
{ {
int32 allocfreetrace; int32 allocfreetrace;
int32 efence;
int32 gctrace; int32 gctrace;
int32 scheddetail; int32 scheddetail;
int32 schedtrace; int32 schedtrace;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment