Skip to content
This repository has been archived by the owner on Feb 8, 2024. It is now read-only.

Commit

Permalink
fibers: implement switching exception information, fix invalid except…
Browse files Browse the repository at this point in the history
…ion chain
  • Loading branch information
rainers committed Jan 29, 2016
1 parent dcece0b commit 9d8f75e
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 4 deletions.
15 changes: 12 additions & 3 deletions src/core/thread.d
Original file line number Diff line number Diff line change
Expand Up @@ -3908,6 +3908,10 @@ version( LDC )
version( X86 ) version = CheckFiberMigration;
version( X86_64 ) version = CheckFiberMigration;
}
else version( Windows )
{
version( X86 ) version = CheckFiberMigration;
}
}

// Fiber support for SjLj style exceptions
Expand Down Expand Up @@ -4854,16 +4858,21 @@ private:
finalHandler = reg.handler;
}

pstack -= EXCEPTION_REGISTRATION.sizeof;
// With safeseh(?), the chain must not extend to the very top
// of the stack, otherwise the exception chain is also considered
// invalid. Reserving additional 4 bytes at the top of the stack will
// keep the EXCEPTION_REGISTRATION below that limit
size_t reserve = EXCEPTION_REGISTRATION.sizeof + 4;
pstack -= reserve;
*(cast(EXCEPTION_REGISTRATION*)pstack) =
EXCEPTION_REGISTRATION( sehChainEnd, finalHandler );

push( cast(size_t) &fiber_entryPoint ); // EIP
push( cast(size_t) m_ctxt.bstack - EXCEPTION_REGISTRATION.sizeof ); // EBP
push( cast(size_t) m_ctxt.bstack - reserve ); // EBP
push( 0x00000000 ); // EDI
push( 0x00000000 ); // ESI
push( 0x00000000 ); // EBX
push( cast(size_t) m_ctxt.bstack - EXCEPTION_REGISTRATION.sizeof ); // FS:[0]
push( cast(size_t) m_ctxt.bstack - reserve ); // FS:[0]
push( cast(size_t) m_ctxt.bstack ); // FS:[4]
push( cast(size_t) m_ctxt.bstack - m_size ); // FS:[8]
push( 0x00000000 ); // EAX
Expand Down
3 changes: 3 additions & 0 deletions src/ldc/eh/common.d
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ extern(C) void fatalerror(in char* format, ...)
abort();
}

version(Win32) {} else version = notMSVC;
version(notMSVC):

// ------------------------
// Reading DWARF data
// ------------------------
Expand Down
68 changes: 67 additions & 1 deletion src/ldc/eh/win32.d
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,14 @@ nothrow:

@property size_t length() const { return _length; }
@property bool empty() const { return !length; }


void swap(ref ExceptionStack other)
{
auto olength = other._length; other._length = _length; _length = olength;
auto op = other._p; other._p = _p; _p = op;
auto ocap = other._cap; other._cap = _cap; _cap = ocap;
}

private:
void grow()
{
Expand Down Expand Up @@ -458,7 +465,66 @@ int doRtlUnwind(void* pFrame, ExceptionRecord* eRecord, typeof(RtlUnwind)* handl
ret;
}
}

///////////////////////////////////////////////////////////////
struct FiberContext
{
ExceptionStack exceptionStack;
void* currentException;
void* currentExceptionContext;
int processingContext;
}

FiberContext* fiberContext;

extern(C) void** __current_exception() nothrow;
extern(C) void** __current_exception_context() nothrow;
extern(C) int* __processing_throw() nothrow;

extern(C) void* _d_eh_swapContext(FiberContext* newContext) nothrow
{
import rt.util.container.common : xmalloc;
import core.stdc.string : memset;
if (!fiberContext)
{
fiberContext = cast(FiberContext*) xmalloc(FiberContext.sizeof);
memset(fiberContext, 0, FiberContext.sizeof);
}
fiberContext.exceptionStack.swap(exceptionStack);
fiberContext.currentException = *__current_exception();
fiberContext.currentExceptionContext = *__current_exception_context();
fiberContext.processingContext = *__processing_throw();

if (newContext)
{
exceptionStack.swap(newContext.exceptionStack);
*__current_exception() = newContext.currentException;
*__current_exception_context() = newContext.currentExceptionContext;
*__processing_throw() = newContext.processingContext;
}
else
{
exceptionStack = ExceptionStack();
*__current_exception() = null;
*__current_exception_context() = null;
*__processing_throw() = 0;
}

FiberContext* old = fiberContext;
fiberContext = newContext;
return old;
}

static ~this()
{
import core.stdc.stdlib : free;
if (fiberContext)
{
destroy(*fiberContext);
free(fiberContext);
}
}

///////////////////////////////////////////////////////////////
void msvc_eh_init()
{
Expand Down

0 comments on commit 9d8f75e

Please sign in to comment.