-
-
Notifications
You must be signed in to change notification settings - Fork 409
add support for linux dynamic dll loading #583
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -243,21 +243,19 @@ extern (C) bool rt_init(ExceptionHandler dg = null) | |
| initStaticDataGC(); | ||
| rt_moduleCtor(); | ||
| rt_moduleTlsCtor(); | ||
| runModuleUnitTests(); | ||
| return true; | ||
| } | ||
| catch (Throwable e) | ||
| { | ||
| /* Note that if we get here, the runtime is in an unknown state. | ||
| * I'm not sure what the point of calling dg is. | ||
| */ | ||
| if (dg) | ||
| dg(e); | ||
| else | ||
| if (!dg) | ||
| throw e; // rethrow, don't silently ignore error | ||
| /* Rethrow, and the two STD functions aren't called? | ||
| * This needs rethinking. | ||
| */ | ||
| /* Rethrow, and the two STD functions aren't called? | ||
| * This needs rethinking. | ||
| */ | ||
| dg(e); | ||
| } | ||
| _STD_critical_term(); | ||
| _STD_monitor_staticdtor(); | ||
|
|
@@ -284,8 +282,9 @@ extern (C) bool rt_term(ExceptionHandler dg = null) | |
| } | ||
| catch (Throwable e) | ||
| { | ||
| if (dg) | ||
| dg(e); | ||
| if (!dg) | ||
| throw e; // rethrow, don't silently ignore error | ||
| dg(e); | ||
| } | ||
| finally | ||
| { | ||
|
|
@@ -375,9 +374,6 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc) | |
| } | ||
| } | ||
|
|
||
| _STI_monitor_staticctor(); | ||
| _STI_critical_init(); | ||
|
|
||
| // Allocate args[] on the stack | ||
| char[][] args = (cast(char[]*) alloca(argc * (char[]).sizeof))[0 .. argc]; | ||
|
|
||
|
|
@@ -560,27 +556,27 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc) | |
|
|
||
| void runAll() | ||
| { | ||
| initSections(); | ||
| gc_init(); | ||
| initStaticDataGC(); | ||
| rt_moduleCtor(); | ||
| rt_moduleTlsCtor(); | ||
| version (linux) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should probably copy the comment here as this is more likely the place people will look and wonder "what's going on here?"
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copy what comment? |
||
| { } | ||
| else | ||
| rt_init(); | ||
|
|
||
| if (runModuleUnitTests()) | ||
| tryExec(&runMain); | ||
| else | ||
| result = EXIT_FAILURE; | ||
| rt_moduleTlsDtor(); | ||
| thread_joinAll(); | ||
| rt_moduleDtor(); | ||
| gc_term(); | ||
| finiSections(); | ||
|
|
||
| version (linux) | ||
| { } | ||
| else | ||
| { | ||
| if (!rt_term() && result == EXIT_SUCCESS) | ||
| result = EXIT_FAILURE; | ||
| } | ||
| } | ||
|
|
||
| tryExec(&runAll); | ||
|
|
||
| _STD_critical_term(); | ||
| _STD_monitor_staticdtor(); | ||
|
|
||
| // Issue 10344: flush stdout and return nonzero on failure | ||
| if (.fflush(.stdout) != 0) | ||
| { | ||
|
|
@@ -593,3 +589,30 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc) | |
|
|
||
| return result; | ||
| } | ||
|
|
||
| version (linux) | ||
| { | ||
| /* Startup and shutdown is done with static construction/destruction | ||
| */ | ||
|
|
||
| //import core.stdc.stdio; | ||
| shared static this() | ||
| { | ||
| //printf("dmain2\n"); | ||
| _STI_monitor_staticctor(); | ||
| _STI_critical_init(); | ||
| initSections(); | ||
| gc_init(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This call chain comes to early gc_init=>thread_init=>thread_attachThis=>rt.sections_linux.initTLSRanges, because it makes the implicit assumption that all libraries are already loaded. It will miss the TLS ranges from anything but libphobos2.so. |
||
| initStaticDataGC(); | ||
| } | ||
|
|
||
| shared static ~this() | ||
| { | ||
| //printf("~dmain2\n"); | ||
| //thread_joinAll(); | ||
| gc_term(); | ||
| finiSections(); | ||
| _STD_critical_term(); | ||
| _STD_monitor_staticdtor(); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this really work the way we want? Since there's no dependency tree here, it seems like this static dtor will be run in a random order with the others, and so some static dtors will be run after the GC and runtime are completely shut down.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In minfo.d, I added code specifically to run this ctor first, and this dtor last.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just call rt_init within the first call to _d_dso_registry and rt_term when the last library unregisters. This is dead simple and you can scratch all the code to treat rt.dmain2 specially. |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,8 +12,9 @@ | |
|
|
||
| module rt.minfo; | ||
|
|
||
| import core.stdc.stdlib; // alloca | ||
| import core.stdc.string; // memcpy | ||
| import core.stdc.stdlib; | ||
| import core.stdc.string; | ||
| import core.stdc.stdio : printf; | ||
| import rt.sections; | ||
|
|
||
| enum | ||
|
|
@@ -46,6 +47,7 @@ struct ModuleGroup | |
| this(ModuleInfo*[] modules) | ||
| { | ||
| _modules = modules; | ||
| first = null; | ||
| } | ||
|
|
||
| @property inout(ModuleInfo*)[] modules() inout | ||
|
|
@@ -92,6 +94,7 @@ struct ModuleGroup | |
| size_t cidx; | ||
|
|
||
| ModuleInfo*[] mods = _modules; | ||
|
|
||
| size_t idx; | ||
| while (true) | ||
| { | ||
|
|
@@ -169,6 +172,8 @@ struct ModuleGroup | |
| stack[stackidx++] = StackRec(mods, idx); | ||
| idx = 0; | ||
| mods = m.importedModules; | ||
| //printf("m %.*s imports:\n", m.name.length, m.name.ptr); | ||
| //foreach (m2; mods) printf("\t%.*s\n", m2.name.length, m2.name.ptr); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -195,6 +200,18 @@ struct ModuleGroup | |
| m.flags = m.flags & ~(MIctorstart | MIctordone); | ||
| } | ||
|
|
||
| /* Look for module rt.dmain2, and put that as first ctor to run | ||
| */ | ||
| foreach (m; _modules) | ||
| { | ||
| if (m.name == "rt.dmain2" && m.ctor) | ||
| { | ||
| first = m; | ||
| m.flags = m.flags | MIctordone; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| /* Do two passes: ctor/dtor, tlsctor/tlsdtor | ||
| */ | ||
| sort(_ctors, MIctor | MIdtor); | ||
|
|
@@ -203,6 +220,19 @@ struct ModuleGroup | |
|
|
||
| void runCtors() | ||
| { | ||
| version (none) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer to turn printf's on individually as desired. Turning on a bunch with a global flag tends to produce a blizzard of senseless output. |
||
| { | ||
| foreach (m; _modules) | ||
| printf("module %.*s\n", m.name.length, m.name.ptr); | ||
| foreach (m; _ctors) | ||
| printf("ctor %.*s\n", m.name.length, m.name.ptr); | ||
| } | ||
|
|
||
| if (first) | ||
| { | ||
| (*first.ctor)(); | ||
| } | ||
|
|
||
| // run independent ctors | ||
| runModuleFuncs!(m => m.ictor)(_modules); | ||
| // sorted module ctors | ||
|
|
@@ -225,6 +255,9 @@ struct ModuleGroup | |
| void runDtors() | ||
| { | ||
| runModuleFuncsRev!(m => m.dtor)(_ctors); | ||
| if (first && first.dtor) | ||
| (*first.dtor)(); | ||
|
|
||
| // clean all initialized flags | ||
| foreach (m; _modules) | ||
| m.flags = m.flags & ~MIctordone; | ||
|
|
@@ -245,6 +278,8 @@ private: | |
| ModuleInfo*[] _modules; | ||
| ModuleInfo*[] _ctors; | ||
| ModuleInfo*[] _tlsctors; | ||
| public: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why public I wonder
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because sections_linux.d accesses first. |
||
| ModuleInfo* first; | ||
| } | ||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine with me, but should be separate commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine even though rt_init() is being called from C code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that I adjusted the behavior of rt_term() to match that of rt_init() in regards to exceptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, when this propagates to all platforms, rt_init() will no longer be called by C code. The initialization will happen automatically, just by loading the DLL using the operating system call to do so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd write this as
i.e. minimize flow control.