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

Commit fa62b2e

Browse files
committed
fibers: implement switching exception information, fix invalid exception chain
1 parent dcece0b commit fa62b2e

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

src/core/thread.d

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3908,6 +3908,10 @@ version( LDC )
39083908
version( X86 ) version = CheckFiberMigration;
39093909
version( X86_64 ) version = CheckFiberMigration;
39103910
}
3911+
else version( Windows )
3912+
{
3913+
version( X86 ) version = CheckFiberMigration;
3914+
}
39113915
}
39123916

39133917
// Fiber support for SjLj style exceptions
@@ -4831,6 +4835,11 @@ private:
48314835
{
48324836
EXCEPTION_REGISTRATION* next; // sehChainEnd if last one.
48334837
fp_t handler;
4838+
// With safeseh(?), the chain must not extend to the very top
4839+
// of the stack, otherwise the exception chain is also considered
4840+
// invalid. Adding a filler to the end of this struct to will
4841+
// keep the EXCEPTION_REGISTRATION below that limit
4842+
size_t filler;
48344843
}
48354844
enum sehChainEnd = cast(EXCEPTION_REGISTRATION*) 0xFFFFFFFF;
48364845

src/ldc/eh/common.d

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ extern(C) void fatalerror(in char* format, ...)
3636
abort();
3737
}
3838

39+
version(Win32) {} else version = notMSVC;
40+
version(notMSVC):
41+
3942
// ------------------------
4043
// Reading DWARF data
4144
// ------------------------

src/ldc/eh/win32.d

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ extern(C) void _d_throw_exception(Object e)
115115
auto ti = typeid(e);
116116
if (ti is null)
117117
fatalerror("Cannot throw corrupt exception object with null classinfo");
118+
119+
debug asm { mov EAX,FS:[0]; }
118120

119121
exceptionStack.push(cast(Throwable) e);
120122

@@ -279,6 +281,13 @@ nothrow:
279281
@property size_t length() const { return _length; }
280282
@property bool empty() const { return !length; }
281283

284+
void swap(ref ExceptionStack other)
285+
{
286+
auto olength = other._length; other._length = _length; _length = olength;
287+
auto op = other._p; other._p = _p; _p = op;
288+
auto ocap = other._cap; other._cap = _cap; _cap = ocap;
289+
}
290+
282291
private:
283292
void grow()
284293
{
@@ -459,6 +468,55 @@ int doRtlUnwind(void* pFrame, ExceptionRecord* eRecord, typeof(RtlUnwind)* handl
459468
}
460469
}
461470

471+
///////////////////////////////////////////////////////////////
472+
struct FiberContext
473+
{
474+
ExceptionStack exceptionStack;
475+
void* currentException;
476+
void* currentExceptionContext;
477+
int processingContext;
478+
}
479+
480+
FiberContext* fiberContext;
481+
482+
extern(C) void** __current_exception() nothrow;
483+
extern(C) void** __current_exception_context() nothrow;
484+
extern(C) int* __processing_throw() nothrow;
485+
486+
extern(C) void* _d_eh_swapContext(FiberContext* newContext) nothrow
487+
{
488+
import rt.util.container.common : xmalloc;
489+
import core.stdc.string : memset;
490+
if (!fiberContext)
491+
{
492+
fiberContext = cast(FiberContext*) xmalloc(FiberContext.sizeof);
493+
memset(fiberContext, 0, FiberContext.sizeof);
494+
}
495+
fiberContext.exceptionStack.swap(exceptionStack);
496+
fiberContext.currentException = *__current_exception();
497+
fiberContext.currentExceptionContext = *__current_exception_context();
498+
fiberContext.processingContext = *__processing_throw();
499+
500+
if (newContext)
501+
{
502+
exceptionStack.swap(newContext.exceptionStack);
503+
*__current_exception() = newContext.currentException;
504+
*__current_exception_context() = newContext.currentExceptionContext;
505+
*__processing_throw() = newContext.processingContext;
506+
}
507+
else
508+
{
509+
exceptionStack = ExceptionStack();
510+
*__current_exception() = null;
511+
*__current_exception_context() = null;
512+
*__processing_throw() = 0;
513+
}
514+
515+
FiberContext* old = fiberContext;
516+
fiberContext = newContext;
517+
return old;
518+
}
519+
462520
///////////////////////////////////////////////////////////////
463521
void msvc_eh_init()
464522
{

0 commit comments

Comments
 (0)