Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1407 from MartinNowak/merge_stable
Browse files Browse the repository at this point in the history
Merge remote-tracking branch 'upstream/stable' into merge_stable
  • Loading branch information
9rnsr committed Oct 14, 2015
2 parents d42d96c + b6db35e commit df44431
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 42 deletions.
31 changes: 30 additions & 1 deletion src/core/exception.d
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class FinalizeError : Error
this( TypeInfo ci, string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @safe pure nothrow @nogc
{
super( "Finalization error", file, line, next );
super.info = SuppressTraceInfo.instance;
info = ci;
}

Expand Down Expand Up @@ -214,7 +215,14 @@ class OutOfMemoryError : Error
{
this(string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @safe pure nothrow @nogc
{
super( "Memory allocation failed", file, line, next );
this(true, file, line, next);
}

this(bool trace, string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @safe pure nothrow @nogc
{
super("Memory allocation failed", file, line, next);
if (!trace)
this.info = SuppressTraceInfo.instance;
}

override string toString() const @trusted
Expand Down Expand Up @@ -256,6 +264,7 @@ class InvalidMemoryOperationError : Error
this(string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @safe pure nothrow @nogc
{
super( "Invalid memory operation", file, line, next );
this.info = SuppressTraceInfo.instance;
}

override string toString() const @trusted
Expand Down Expand Up @@ -519,6 +528,12 @@ extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure
throw staticError!OutOfMemoryError();
}

extern (C) void onOutOfMemoryErrorNoGC() @trusted nothrow @nogc
{
// suppress stacktrace until they are @nogc
throw staticError!OutOfMemoryError(false);
}


/**
* A callback for invalid memory operations in D. An
Expand Down Expand Up @@ -664,3 +679,17 @@ private T staticError(T, Args...)(auto ref Args args)
res.__ctor(args);
return res;
}

// Suppress traceinfo generation when the GC cannot be used. Workaround for
// Bugzilla 14993. We should make stack traces @nogc instead.
private class SuppressTraceInfo : Throwable.TraceInfo
{
override int opApply(scope int delegate(ref const(char[]))) const { return 0; }
override int opApply(scope int delegate(ref size_t, ref const(char[]))) const { return 0; }
override string toString() const { return null; }
static SuppressTraceInfo instance() @trusted @nogc pure nothrow
{
static immutable SuppressTraceInfo it = new SuppressTraceInfo;
return cast(SuppressTraceInfo)it;
}
}
18 changes: 9 additions & 9 deletions src/gc/gc.d
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ private
// Declared as an extern instead of importing core.exception
// to avoid inlining - see issue 13725.
void onInvalidMemoryOperationError() nothrow;
void onOutOfMemoryError() nothrow;
void onOutOfMemoryErrorNoGC() @nogc nothrow;
}

enum
Expand Down Expand Up @@ -199,14 +199,14 @@ debug (LOGGING)
{
data = cast(Log*)cstdlib.malloc(allocdim * Log.sizeof);
if (!data && allocdim)
onOutOfMemoryError();
onOutOfMemoryErrorNoGC();
}
else
{ Log *newdata;

newdata = cast(Log*)cstdlib.malloc(allocdim * Log.sizeof);
if (!newdata && allocdim)
onOutOfMemoryError();
onOutOfMemoryErrorNoGC();
memcpy(newdata, data, dim * Log.sizeof);
cstdlib.free(data);
data = newdata;
Expand Down Expand Up @@ -296,7 +296,7 @@ struct GC
gcLock.__ctor();
gcx = cast(Gcx*)cstdlib.calloc(1, Gcx.sizeof);
if (!gcx)
onOutOfMemoryError();
onOutOfMemoryErrorNoGC();
gcx.initialize();

if (config.initReserve)
Expand Down Expand Up @@ -526,7 +526,7 @@ struct GC

auto p = gcx.alloc(size + SENTINEL_EXTRA, alloc_size, bits);
if (!p)
onOutOfMemoryError();
onOutOfMemoryErrorNoGC();

debug (SENTINEL)
{
Expand Down Expand Up @@ -1805,7 +1805,7 @@ struct Gcx
// tryAlloc will succeed if a new pool was allocated above, if it fails allocate a new pool now
if (!tryAlloc() && (!newPool(1, false) || !tryAlloc()))
// out of luck or memory
onOutOfMemoryError();
onOutOfMemoryErrorNoGC();
}
assert(p !is null);

Expand Down Expand Up @@ -2021,7 +2021,7 @@ struct Gcx
enum initSize = 64 * 1024; // Windows VirtualAlloc granularity
immutable ncap = _cap ? 2 * _cap : initSize / Range.sizeof;
auto p = cast(Range*)os_mem_map(ncap * Range.sizeof);
if (p is null) onOutOfMemoryError();
if (p is null) onOutOfMemoryErrorNoGC();
if (_p !is null)
{
p[0 .. _length] = _p[0 .. _length];
Expand Down Expand Up @@ -2722,13 +2722,13 @@ struct Pool

pagetable = cast(ubyte*)cstdlib.malloc(npages);
if (!pagetable)
onOutOfMemoryError();
onOutOfMemoryErrorNoGC();

if(isLargeObject)
{
bPageOffsets = cast(uint*)cstdlib.malloc(npages * uint.sizeof);
if (!bPageOffsets)
onOutOfMemoryError();
onOutOfMemoryErrorNoGC();
}

memset(pagetable, B_FREE, npages);
Expand Down
21 changes: 7 additions & 14 deletions src/rt/lifetime.d
Original file line number Diff line number Diff line change
Expand Up @@ -2571,16 +2571,13 @@ unittest
import core.exception;
static class C1
{
// preallocate to not call new in destructor
__gshared E exc = new E("test onFinalizeError");
~this()
{
throw exc;
}
E exc;
this(E exc) { this.exc = exc; }
~this() { throw exc; }
}

bool caught = false;
C1 c = new C1;
C1 c = new C1(new E("test onFinalizeError"));
try
{
GC.runFinalizers((cast(uint*)&C1.__dtor)[0..1]);
Expand Down Expand Up @@ -2613,16 +2610,12 @@ unittest
import core.exception;
static struct S1
{
// preallocate to not call new in destructor
__gshared E exc = new E("test onFinalizeError");
~this()
{
throw exc;
}
E exc;
~this() { throw exc; }
}

bool caught = false;
S1* s = new S1;
S1* s = new S1(new E("test onFinalizeError"));
try
{
GC.runFinalizers((cast(char*)(typeid(S1).xdtor))[0..1]);
Expand Down
29 changes: 11 additions & 18 deletions test/exceptions/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include ../common.mak

TESTS:=stderr_msg unittest_assert
TESTS:=stderr_msg unittest_assert invalid_memory_operation
ifeq ($(OS)-$(BUILD),linux-debug)
TESTS:=$(TESTS) line_trace
endif
Expand All @@ -14,26 +14,19 @@ SED:=sed
.PHONY: all clean
all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS)))

$(ROOT)/%.done: $(ROOT)/%
@echo Testing $*
$(QUIET)$(ROOT)/$* $(RUN_ARGS)
@touch $@

$(ROOT)/stderr_msg.done: $(ROOT)/stderr_msg
@echo Testing stderr_msg
$(QUIET)./$(ROOT)/stderr_msg $(RUN_ARGS) 2>&1 1>/dev/null | grep -qF "stderr_msg msg"
@touch $@

$(ROOT)/unittest_assert.done: $(ROOT)/unittest_assert
@echo Testing unittest_assert
$(QUIET)./$(ROOT)/unittest_assert $(RUN_ARGS) 2>&1 1>/dev/null | grep -qF "unittest_assert msg"
@touch $@

$(ROOT)/line_trace.done: $(ROOT)/line_trace
@echo Testing line_trace
@rm -f $(ROOT)/line_trace.output
$(QUIET)./$(ROOT)/line_trace $(RUN_ARGS) > $(ROOT)/line_trace.output
$(QUIET)$(ROOT)/line_trace $(RUN_ARGS) > $(ROOT)/line_trace.output
$(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g" $(ROOT)/line_trace.output | $(DIFF) line_trace.exp -
@rm -f $(ROOT)/line_trace.output
@touch $@

$(ROOT)/stderr_msg.done: STDERR_EXP="stderr_msg msg"
$(ROOT)/unittest_assert.done: STDERR_EXP="unittest_assert msg"
$(ROOT)/invalid_memory_operation.done: STDERR_EXP="InvalidMemoryOperationError"
$(ROOT)/%.done: $(ROOT)/%
@echo Testing $*
$(QUIET)$(ROOT)/$* $(RUN_ARGS) 2>&1 1>/dev/null | grep -qF $(STDERR_EXP)
@touch $@

$(ROOT)/unittest_assert: DFLAGS+=-unittest
Expand Down
12 changes: 12 additions & 0 deletions test/exceptions/src/invalid_memory_operation.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
struct S
{
~this()
{
new int;
}
}

void main()
{
new S;
}

0 comments on commit df44431

Please sign in to comment.