www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Proper way to exit with specific exit code?

reply drathier <forum.dlang.org fi.fo> writes:
What's the proper way to exit with a specific exit code?

I found a bunch of old threads discussing this, making sure 
destructors run and the runtime terminates properly, all of which 
seemingly concluding that it's sad that there isn't a way to do 
this easily, but hopefully things have changed in the last 5-10 
years and I'm just missing the obvious solution.
Sep 17 2020
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Sep 17, 2020 at 02:58:48PM +0000, drathier via Digitalmars-d-learn
wrote:
 What's the proper way to exit with a specific exit code?
 
 I found a bunch of old threads discussing this, making sure
 destructors run and the runtime terminates properly, all of which
 seemingly concluding that it's sad that there isn't a way to do this
 easily, but hopefully things have changed in the last 5-10 years and
 I'm just missing the obvious solution.
AFAIK, there still isn't an "official" way to do this besides return the exit code from main(). My go-to solution is to declare an ExitException that's explicitly caught by main(): class ExitException : Exception { int returnCode; this() { super("exit"); } } void exit(int rc=0) { throw new ExitException(rc); } int main(string[] args) { try { ... // your code here exit(123); ... } catch (ExitException e) { return e.returnCode; } return 0; } Caveat: this may or may not do the Right Thing(tm) in a multithreaded application. T -- Talk is cheap. Whining is actually free. -- Lars Wirzenius
Sep 17 2020
prev sibling next sibling parent reply IGotD- <nise nise.com> writes:
On Thursday, 17 September 2020 at 14:58:48 UTC, drathier wrote:
 What's the proper way to exit with a specific exit code?

 I found a bunch of old threads discussing this, making sure 
 destructors run and the runtime terminates properly, all of 
 which seemingly concluding that it's sad that there isn't a way 
 to do this easily, but hopefully things have changed in the 
 last 5-10 years and I'm just missing the obvious solution.
The only way is to return from main. The thing is that druntime runs initialization before main and then returning from main it runs all the tear down code including cleaning up the GC. This means there is no equivalent of the exit function in the C library. Calling exit from D means that there will be no cleanup in D environment. This is a bit limiting for my needs for example. I would like that exiting from main will not tear down the D runtime because my system is a message driven system and main just sets up the program and then returns but the programs continues to react on messages. Many libraries like Qt circumvents this just by parking the main thread as a event handler but this doesn't fit my system and will waste one thread resource. Finally to exit the program I have equivalent to the C library exit function. Creating a similar exit function in D would be trivial really.
Sep 17 2020
parent reply James Blachly <james.blachly gmail.com> writes:
On 9/17/20 12:46 PM, IGotD- wrote:
 The only way is to return from main. The thing is that druntime runs 
 initialization before main and then returning from main it runs all the 
 tear down code including cleaning up the GC. This means there is no 
 equivalent of the exit function in the C library. Calling exit from D 
 means that there will be no cleanup in D environment.
... I never considered this -- so when I call core.stdc.stdlib : exit, none of my destructors get called? Presumably also not scope(exit) blocks? If this is the case, could we simply add a publically-accessible shutdown hook in the runtime?
Sep 17 2020
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Sep 17, 2020 at 09:53:07PM -0400, James Blachly via Digitalmars-d-learn
wrote:
[...]
 I never considered this -- so when I call core.stdc.stdlib : exit,
 none of my destructors get called?
Yes.
 Presumably also not scope(exit) blocks?
Yes.
 If this is the case, could we simply add a publically-accessible
 shutdown hook in the runtime?
That's the obvious solution, except that actually implementing it is not so simple. When you have multiple threads listening for each other and/or doing work, there is no 100% guaranteed way of cleanly shutting all of them down at the same time. You can't just clean up the calling thread and leave the others running, because the other threads might hold references to your data, etc.. But there's no universal protocol for shutting down the other threads too -- they could be in a busy loop with some long-running computation, or they may not be checking for thread messages, or they could be in a server loop that is designed to keep running, etc.. It's one of those annoying things that reduce to the halting problem in the general case. Unless we adopt some kind of exit protocol that will apply to *all* threads in *all* D programs, I don't see any way to implement something that will work in the general case. T -- If blunt statements had a point, they wouldn't be blunt...
Sep 17 2020
parent reply IGotD- <nise nise.com> writes:
On Friday, 18 September 2020 at 05:02:21 UTC, H. S. Teoh wrote:
 That's the obvious solution, except that actually implementing 
 it is not so simple.  When you have multiple threads listening 
 for each other and/or doing work, there is no 100% guaranteed 
 way of cleanly shutting all of them down at the same time.  You 
 can't just clean up the calling thread and leave the others 
 running, because the other threads might hold references to 
 your data, etc..  But there's no universal protocol for 
 shutting down the other threads too -- they could be in a busy 
 loop with some long-running computation, or they may not be 
 checking for thread messages, or they could be in a server loop 
 that is designed to keep running, etc..  It's one of those 
 annoying things that reduce to the halting problem in the 
 general case.

 Unless we adopt some kind of exit protocol that will apply to 
 *all* threads in *all* D programs, I don't see any way to 
 implement something that will work in the general case.


 T
I think a pragmatic solution is just to mutex protect the D exit function in case several threads tries to use simultaneously. Then if more threads call exit, it will do nothing as the first one that called exit actually do the tear down. Also, it should be responsibility of the program to ensure that its tear down code runs before calling the D exit function. That's the only way I can think of because waiting for all other threads to release their resources and exit isn't really realistic either as that might do that the program exit never happens. Whatever you do you, you have to resort to some "manual" solution". I suggest keeping it simple and stupid.
Sep 18 2020
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Sep 18, 2020 at 08:20:59AM +0000, IGotD- via Digitalmars-d-learn wrote:
 On Friday, 18 September 2020 at 05:02:21 UTC, H. S. Teoh wrote:
 
 That's the obvious solution, except that actually implementing it is not
 so simple.  When you have multiple threads listening for each other
 and/or doing work, there is no 100% guaranteed way of cleanly shutting
 all of them down at the same time.  You can't just clean up the calling
 thread and leave the others running, because the other threads might
 hold references to your data, etc..  But there's no universal protocol
 for shutting down the other threads too -- they could be in a busy loop
 with some long-running computation, or they may not be checking for
 thread messages, or they could be in a server loop that is designed to
 keep running, etc..  It's one of those annoying things that reduce to
 the halting problem in the general case.
[...]
 I think a pragmatic solution is just to mutex protect the D exit
 function in case several threads tries to use simultaneously. Then if
 more threads call exit, it will do nothing as the first one that
 called exit actually do the tear down.
That does not solve the problem. If thread 1 calls exit but thread 2 is still running and processing data via a shared reference with thread 1's data, you absolutely do not want to run dtors and tear-down code until thread 2 is done, otherwise you have a problem. OTOH, waiting for thread 2 to finish first comes with its own problems: what if thread 2 never calls exit? Then no cleanup will be done, which may not be desirable either (maybe you had thread 1 call exit because you wanted to release unused resources).
 Also, it should be responsibility of the program to ensure that its
 tear down code runs before calling the D exit function. That's the
 only way I can think of because waiting for all other threads to
 release their resources and exit isn't really realistic either as that
 might do that the program exit never happens. Whatever you do you, you
 have to resort to some "manual" solution".
[...] If you're prepared to do manual teardown, then you do not need a D-specific exit function. Just call core.sys.stdc.stdlib.exit and call it a day. :-) T -- Never trust an operating system you don't have source for! -- Martin Schulze
Sep 18 2020
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2020-09-17 16:58, drathier wrote:
 What's the proper way to exit with a specific exit code?
 
 I found a bunch of old threads discussing this, making sure destructors 
 run and the runtime terminates properly, all of which seemingly 
 concluding that it's sad that there isn't a way to do this easily, but 
 hopefully things have changed in the last 5-10 years and I'm just 
 missing the obvious solution.
The proper way is: int main() { return 42; } I highly recommend against trying to terminate the application using `exit` or any other way. Just let the control flow return back to the `main` function. -- /Jacob Carlborg
Sep 18 2020
parent reply mw <mingwu gmail.com> writes:
On Saturday, 19 September 2020 at 06:11:15 UTC, Jacob Carlborg 
wrote:
 On 2020-09-17 16:58, drathier wrote:
 What's the proper way to exit with a specific exit code?
 
 I found a bunch of old threads discussing this, making sure 
 destructors run and the runtime terminates properly, all of 
 which seemingly concluding that it's sad that there isn't a 
 way to do this easily, but hopefully things have changed in 
 the last 5-10 years and I'm just missing the obvious solution.
The proper way is: int main() { return 42; } I highly recommend against trying to terminate the application using `exit` or any other way. Just let the control flow return back to the `main` function.
I'm facing this problem to exit early from a multi threaded program for mem profiling purpose: https://forum.dlang.org/thread/zbdevevgghtdgfryuymh forum.dlang.org So what the simplest and reliable way to terminate all threads and exit to os? I even tried core.stdc.stdlib.exit(-1), it does not work.
Nov 13 2022
next sibling parent reply mw <mingwu gmail.com> writes:
On Sunday, 13 November 2022 at 21:16:32 UTC, mw wrote:

 I even tried core.stdc.stdlib.exit(-1), it does not work.
Tried ``` import core.runtime; Runtime.terminate(); core.stdc.stdlib.exit(-1); ``` Still does not work.
Nov 13 2022
parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Sunday, 13 November 2022 at 21:37:47 UTC, mw wrote:
 On Sunday, 13 November 2022 at 21:16:32 UTC, mw wrote:

 I even tried core.stdc.stdlib.exit(-1), it does not work.
Tried ``` import core.runtime; Runtime.terminate(); core.stdc.stdlib.exit(-1); ``` Still does not work.
I have no idea why it would fail. What about assert(0)?
Nov 13 2022
parent reply mw <mingwu gmail.com> writes:
On Sunday, 13 November 2022 at 22:06:09 UTC, Imperatorn wrote:
 On Sunday, 13 November 2022 at 21:37:47 UTC, mw wrote:
 On Sunday, 13 November 2022 at 21:16:32 UTC, mw wrote:

 I even tried core.stdc.stdlib.exit(-1), it does not work.
Tried ``` import core.runtime; Runtime.terminate(); core.stdc.stdlib.exit(-1); ``` Still does not work.
I have no idea why it would fail. What about assert(0)?
I guess these two calls somehow only terminate the calling thread (? this is strange for core.stdc.stdlib.exit), the whole program just hangs after the call, and can only be terminated by `kill -9`. I have to manually go thru each of the treads and plug in some kind of early exit logic to stop the whole program. Will try assert(0) later.
Nov 13 2022
parent reply mw <mingwu gmail.com> writes:
On Sunday, 13 November 2022 at 22:17:32 UTC, mw wrote:
 On Sunday, 13 November 2022 at 22:06:09 UTC, Imperatorn wrote:
 On Sunday, 13 November 2022 at 21:37:47 UTC, mw wrote:
 On Sunday, 13 November 2022 at 21:16:32 UTC, mw wrote:

 I even tried core.stdc.stdlib.exit(-1), it does not work.
Tried ``` import core.runtime; Runtime.terminate(); core.stdc.stdlib.exit(-1); ``` Still does not work.
I have no idea why it would fail. What about assert(0)?
I guess these two calls somehow only terminate the calling thread (? this is strange for core.stdc.stdlib.exit), the whole program just hangs after the call, and can only be terminated by `kill -9`. I have to manually go thru each of the treads and plug in some kind of early exit logic to stop the whole program. Will try assert(0) later.
tried: ``` core.runtime.Runtime.terminate(); core.stdc.stdlib.exit(-1); assert(0); enforce(false); ``` Still not working, not even "Ctrl+C", have to `kill -9` to terminate it.
Nov 13 2022
parent mw <mingwu gmail.com> writes:
On Sunday, 13 November 2022 at 22:42:45 UTC, mw wrote:
 On Sunday, 13 November 2022 at 22:17:32 UTC, mw wrote:
 On Sunday, 13 November 2022 at 22:06:09 UTC, Imperatorn wrote:
 On Sunday, 13 November 2022 at 21:37:47 UTC, mw wrote:
 On Sunday, 13 November 2022 at 21:16:32 UTC, mw wrote:

 I even tried core.stdc.stdlib.exit(-1), it does not work.
Tried ``` import core.runtime; Runtime.terminate(); core.stdc.stdlib.exit(-1); ``` Still does not work.
I have no idea why it would fail. What about assert(0)?
I guess these two calls somehow only terminate the calling thread (? this is strange for core.stdc.stdlib.exit), the whole program just hangs after the call, and can only be terminated by `kill -9`. I have to manually go thru each of the treads and plug in some kind of early exit logic to stop the whole program. Will try assert(0) later.
tried: ``` core.runtime.Runtime.terminate(); core.stdc.stdlib.exit(-1); assert(0); enforce(false); ``` Still not working, not even "Ctrl+C", have to `kill -9` to terminate it.
Tried put assert(0) at the top: ``` assert(0); enforce(false); core.runtime.Runtime.terminate(); core.stdc.stdlib.exit(-1); ``` Seems cannot even terminate the calling thread, since I got that assertion error thousands of times in the log.
Nov 13 2022
prev sibling parent Ruby The Roobster <rubytheroobster yandex.com> writes:
On Sunday, 13 November 2022 at 21:16:32 UTC, mw wrote:
 On Saturday, 19 September 2020 at 06:11:15 UTC, Jacob Carlborg 
 wrote:
 On 2020-09-17 16:58, drathier wrote:
 What's the proper way to exit with a specific exit code?
 
 I found a bunch of old threads discussing this, making sure 
 destructors run and the runtime terminates properly, all of 
 which seemingly concluding that it's sad that there isn't a 
 way to do this easily, but hopefully things have changed in 
 the last 5-10 years and I'm just missing the obvious solution.
The proper way is: int main() { return 42; } I highly recommend against trying to terminate the application using `exit` or any other way. Just let the control flow return back to the `main` function.
I'm facing this problem to exit early from a multi threaded program for mem profiling purpose: https://forum.dlang.org/thread/zbdevevgghtdgfryuymh forum.dlang.org So what the simplest and reliable way to terminate all threads and exit to os? I even tried core.stdc.stdlib.exit(-1), it does not work.
Just give the threads a killswitch, pass the killswitch method to all of the threads, wait for all the threads to exit, and then return. If this doesn't work, than I don't know what will.
Nov 13 2022