www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - What happens when you launch a D application ?

reply "Suliman" <evermind live.ru> writes:
On SO[1] I got next answer:

"What happens when you launch a D application ? The entry point 
is a C main inside the runtime, which initialize it (the 
runtime), including module constructor, run the unittest (if 
you've compiled with -unittest), then call your main (which name 
is "_Dmain" - useful to know if you want to set a breakpoint with 
GDB). When Vibe.d's main is called, it parses command line 
argument, an optional config file, and finally, starts the event 
loop. Any code that wish to run once the event loop has started 
should use runTask and similar, or createTimer. They should not 
call the code directly from the static constructor (it's actually 
one of the most common mistake when starting with Vibe.d)."

Could you explain what mean "C main inside the runtime". I 
thought that is only one main is possible. And why it's named 
"*С* main" D is not C-translated language.

Same question is about _Dmain -- what is it?

If I will call this() before main? What it will be? Will it run 
before main?

[1] 
http://stackoverflow.com/questions/30302161/cant-connect-to-mysql-mariadb-database-from-vibed-app
May 21 2015
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 22 May 2015 at 06:36:27 UTC, Suliman wrote:
 On SO[1] I got next answer:

 "What happens when you launch a D application ? The entry point 
 is a C main inside the runtime, which initialize it (the 
 runtime), including module constructor, run the unittest (if 
 you've compiled with -unittest), then call your main (which 
 name is "_Dmain" - useful to know if you want to set a 
 breakpoint with GDB). When Vibe.d's main is called, it parses 
 command line argument, an optional config file, and finally, 
 starts the event loop. Any code that wish to run once the event 
 loop has started should use runTask and similar, or 
 createTimer. They should not call the code directly from the 
 static constructor (it's actually one of the most common 
 mistake when starting with Vibe.d)."

 Could you explain what mean "C main inside the runtime". I 
 thought that is only one main is possible. And why it's named 
 "*С* main" D is not C-translated language.

 Same question is about _Dmain -- what is it?

 If I will call this() before main? What it will be? Will it run 
 before main?

 [1] 
 http://stackoverflow.com/questions/30302161/cant-connect-to-mysql-mariadb-database-from-vibed-app
Glossing over a lot of the detail: "_Dmain" is the symbol that is generated in the object file for the function called "main" in your source code. A symbol "main" is also generated, which is where the OS starts the whole program*. It sets up the runtime and module constructors etc. and then calls _Dmain. *It's sometimes called the "C main" because it's equivalent to "main" in C.
May 22 2015
parent reply "Suliman" <evermind live.ru> writes:
Am I right understand that that:
1. every App start from main()
2. Dmain is function that run after main is started and it's run 
GC, unit-tests and so on?
May 22 2015
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 22 May 2015 at 11:13:43 UTC, Suliman wrote:
 Am I right understand that that:
 1. every App start from main()
 2. Dmain is function that run after main is started and it's 
 run GC, unit-tests and so on?
Not really, it depends what you mean by main, the function called main that you write in your source code or the function called main that ends up in the actual program? Here's an example: int a; static this() { a = 4; } void main() // { a = 5; } Conceptually speaking, the compiler turns this in to: int a; extern(C) int main() { a = 4; return _Dmain(); } int _Dmain() { a = 5; return 0; } I think that in practice it's more like this: int a; void staticConstructor1() { a = 4; } //actually in druntime int _d_run_main(int function() sourceCodeMain) { staticConstructor1(); // and all the other necessary setup // for the program and runtime sourceCodeMain(); } extern(C) int main() { _d_run_main(&_Dmain); } int _Dmain { a = 5; return 0; }
May 22 2015
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 22 May 2015 at 11:51:01 UTC, John Colvin wrote:
 On Friday, 22 May 2015 at 11:13:43 UTC, Suliman wrote:
 Am I right understand that that:
 1. every App start from main()
 2. Dmain is function that run after main is started and it's 
 run GC, unit-tests and so on?
Not really, it depends what you mean by main, the function called main that you write in your source code or the function called main that ends up in the actual program? Here's an example: int a; static this() { a = 4; } void main() // { a = 5; } Conceptually speaking, the compiler turns this in to: int a; extern(C) int main() { a = 4; return _Dmain(); } int _Dmain() { a = 5; return 0; } I think that in practice it's more like this: int a; void staticConstructor1() { a = 4; } //actually in druntime int _d_run_main(int function() sourceCodeMain) { staticConstructor1(); // and all the other necessary setup // for the program and runtime sourceCodeMain(); } extern(C) int main() { _d_run_main(&_Dmain); } int _Dmain { a = 5; return 0; }
Give or take a few return statements, not that it matters.
May 22 2015
parent reply "Suliman" <evermind live.ru> writes:
Really hard to understand...

So what what would call at first ?
extern(C) int main()
or
int _Dmain()
May 22 2015
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 22 May 2015 at 13:26:32 UTC, Suliman wrote:
 So what what would call at first ?
The operating system starts the program Then the extern(C) int main() gets called. Then the _Dmain gets called.
May 22 2015
prev sibling parent Mike Parker <aldacron gmail.com> writes:
On 5/22/2015 10:26 PM, Suliman wrote:
 Really hard to understand...

 So what what would call at first ?
 extern(C) int main()
 or
 int _Dmain()
Your D programs have multiple layers. There is the C runtime, DRuntime, and your program code. The C runtime is at the bottom. When the program launches, it gets control first. When it has done its work, it looks for a main function and calls it. Normally, in a C program, that would be the main function that you implement. But in D, it is a function implemented by DRuntime. The DRuntime main, because it is called by C, must be declared as extern(C) in order for the C runtime to recognize it. When it is called by the C runtime, then DRuntime does some housekeeping work (calling module constructors, intializing the garbage collecter, and so on). When it is done with that, it then calls the main function that you implemented in your program. The exception to this is when a program is compiled on Windows with WinMain enabled. In this case, the C main is not the entry point, but WinMain is instead. DRuntime does not implement WinMain, so when compiling a D program like this, we have to call initialize DRuntime manually.
May 23 2015
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 5/22/15 2:36 AM, Suliman wrote:
 On SO[1] I got next answer:

 "What happens when you launch a D application ? The entry point is a C
 main inside the runtime, which initialize it (the runtime), including
 module constructor, run the unittest (if you've compiled with
 -unittest), then call your main (which name is "_Dmain" - useful to know
 if you want to set a breakpoint with GDB). When Vibe.d's main is called,
 it parses command line argument, an optional config file, and finally,
 starts the event loop. Any code that wish to run once the event loop has
 started should use runTask and similar, or createTimer. They should not
 call the code directly from the static constructor (it's actually one of
 the most common mistake when starting with Vibe.d)."

 Could you explain what mean "C main inside the runtime". I thought that
 is only one main is possible. And why it's named "*С* main" D is not
 C-translated language.

 Same question is about _Dmain -- what is it?

 If I will call this() before main? What it will be? Will it run before
 main?
Druntime defines the main function that C runtime will call. C runtime intializes its own things (e.g. stdin/stdout/stderr) and then calls C main. Druntime's version of C main then intializes all things that D needs (and there's quite a bit) not in any specific order: - set up the main thread - initialize the GC - detect module constructor/destructor cycles - run module constructors (both shared and thread-local) - run unittests if enabled - run your main function (defined in D as 'main') After main exits, it unwinds all this stuff. FYI, I didn't realize this (but just figured it out), C main *used* to be in druntime, but it's now generated by the compiler. See here: https://github.com/D-Programming-Language/dmd/blob/master/src/mars.c#L236 The function it calls (_d_run_main) is now the entry point into druntime, and it is here: https://github.com/D-Programming-Language/druntime/blob/master/src/rt/dmain2.d#L290 It can give you more clues as to how it works. -Steve
May 22 2015
parent "Mike" <none none.com> writes:
 FYI, I didn't realize this (but just figured it out), C main 
 *used* to be in druntime, but it's now generated by the 
 compiler. See here:

 https://github.com/D-Programming-Language/dmd/blob/master/src/mars.c#L236
True. But it is compiler-dependent. GDC actually still defines "C main" in the runtime: https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/__entrypoint.di#L60 Mike
May 23 2015
prev sibling parent reply "Mike" <none none.com> writes:
 Could you explain what mean "C main inside the runtime". I 
 thought that is only one main is possible. And why it's named 
 "*С* main" D is not C-translated language.

 Same question is about _Dmain -- what is it?

 If I will call this() before main? What it will be? Will it run 
 before main?
This is a great question; one which I've tried to answer through my own investigation. So, I'll add what I've learned. Every D program is started as if it were a C program. This is easiest to see with the GNU toolchain. Try to compile a blank test.c file gcc test.c /usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../lib/crt1.o: In function `_start': (.text+0x20): undefined reference to `main' Now try to compile a blank test.d file gdc test.d /usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../lib/crt1.o: In function `_start': (.text+0x20): undefined reference to `main' {...and a bunch of other errors} So, you can see that both C and D programs need to define an unmangled `main` symbol. We call this symbol "C main". DMD and LDC seem to add "C main" automatically, while GDC defines it in the D runtime: https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/__entrypoint.di#L60 "C main" then calls `_d_run_main`, and passes in a pointer to `_DMain`. `_DMain` is actually a phony alias to your D program's `void main()`, so you won't find it implemented anywhere. Your D program's `void main()` is D-mangled, so it is distinguishable from "C main". We call this symbol "D main" https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/__entrypoint.di#L62 https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/rt/dmain2.d#L235 _d_run_main calls `rt_init()` which does all of the D runtime initialization... https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/rt/dmain2.d#L410 ... and then calls `_DMain` (but it was passed into `_d_run_main as` `mainFunc`: https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/rt/dmain2.d#L411 So in summary it looks like this (At least in Linux): * Operating system calls `_start` which is defined in the C Runtime (crt1.o). * _start calls the unmangled `main` which we will call "C main". This function is automatically added by DMD and LDC, but defined in GDC's D runtime. * "C main" calls `_d_run_main` passing in a pointer to the symbol `_DMain`. `_DMain` is actually your D program's `void main()` function. It is D-mangled, so the linker can distinguish it from "C main" * `_d_run_main` then calls `rt_init()` to initialize the runtime, and then calls `_DMain`. I believe the module constructors and the static constructors are called in D runtime's rt_init function: https://github.com/D-Programming-GDC/GDC/blob/master/libphobos/libdruntime/rt/dmain2.d#L152 I'm still studying how exactly that works, though. I think they are linked into ModuleInfo. I hope this is helpful. If you want to know more about how the operating system calls C main (at least in a Linux environment), see these links: http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html https://gcc.gnu.org/onlinedocs/gccint/Initialization.html Mike
May 23 2015
parent reply "Suliman" <evermind live.ru> writes:
Every D program is started as if it were a C program.
Why is so necessary? What about C++ and other languages? Does they have more then one main? Why it's more than one main is needed? Why D apps can't start with single main?
May 23 2015
next sibling parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 23/05/2015 10:57 p.m., Suliman wrote:
 Every D program is started as if it were a C program.
Why is so necessary? What about C++ and other languages? Does they have more then one main?
Depends on the implementation. I believe Visual C++ does. But it is used like D's to allow it to initialize the runtime. https://msdn.microsoft.com/en-us/library/bb918180.aspx
 Why it's more than one main is needed? Why D apps can't start with
 single main?
Oh but they can. But I guess you'll want things like the GC, module constructors ext oh and some globally initialized memory.
May 23 2015
prev sibling next sibling parent "Mike" <none none.com> writes:
On Saturday, 23 May 2015 at 10:57:22 UTC, Suliman wrote:
Every D program is started as if it were a C program.
Why is so necessary?
It's not actually necessary. You could implement the `_start` function in your D program. Here's a D program without any C runtime, D runtime, or main. long __d_sys_write(long arg1, in void* arg2, long arg3) { ulong result; asm { "syscall" : "=a" result : "a" 1, "D" arg1, "S" arg2, "m" arg2, "d" arg3 : "memory", "cc", "rcx", "r11"; } return result; } extern(C) void __d_sys_exit(long arg1) { asm { "syscall" : : "a" 60, "D" arg1, : "memory", "cc", "rcx", "r11"; } } extern(C) void _start() { // you could put this in a main function and // call main() from here. auto text = "Hello, World!\n"; __d_sys_write(1, text.ptr, text.length); __d_sys_exit(0); } Compile with: gdc -fno-emit-moduleinfo -nostartfiles test.d This produces a 733 byte "Hello World" binary. -fno-emit-moduleinfo will prevent the compiler from generating a lot of auxiliary code that's not needed for this program. -nostartfiles will prevent the C runtime from being linked in. This is a nice little experiment, but once you start trying to use structs, classes, arrays, exceptions, or any other feature of D, you will need more and more of the D runtime. There may also be some things generated by GDC that get called implicitly by the C runtime's initialization procedures (e.g. _init, _fini, etc..) but I'm not that knowledgeable about the compiler's codegen.
 What about C++ and other languages? Does they have more then 
 one main?
C++ is a superset of C, so in my experience, C++ only needs C main. However, C++ has static constructors that get called by some of the initialization procedures in the C runtime before actually calling main. I wonder if C++ free functions mangled in C++...I'm not sure.
 Why it's more than one main is needed? Why D apps can't start 
 with single main?
I don't think the current implementation is necessary. There are probably many different ways to implement D program initialization. I don't see why D runtime couldn't just implement _start, omit the C runtime altogether, and do everything in D, but I trust the compiler implementers have their reasons. If you're interested in digging deeper, you'll probably have to ask questions on D.GNU to get the attention of the compiler implementers. Mike
May 23 2015
prev sibling parent "Maxim Fomin" <maxim-fomin outlook.com> writes:
On Saturday, 23 May 2015 at 10:57:22 UTC, Suliman wrote:
Every D program is started as if it were a C program.
Why is so necessary? What about C++ and other languages? Does they have more then one main? Why it's more than one main is needed? Why D apps can't start with single main?
You could have obtained answer long time ago by using debugger and looking into sources of druntime at github.
May 23 2015