How do you guys handle critical errors?

For example, supose you need to read a file which the program cannot continue executing without it.

You first open the file, then check if it succeeded. Then you somehow get the file size and use it to allocate enought memory. You check it again. Now you are ready to read. If it fails, what do you do?:

1: clear every thing you did before (close the file, free the memory) and exit().
2: just call exit() assuming that the OS will clear everything for you.

I'm asking this because I would love to just call exit(). It is a pain in the ass to always keep looking for things that needs to be cleared if something goes wrong.

I know it is a very simple question, but I would like to know how do you handle this things.

Thanks!

Edited by Leonardo on Reason: Initial post
In general, on desktop (windows, mac, linux, bsd, etc.) and mobile (android, ios) operating systems it's perfectly safe to expect that the OS will reclaim memory and file handles from your process when it exits. For some other resources however, like network sockets, this is not guaranteed to happen immediately, so you should clean them up explicitly before exiting. It's usually easy enough to maintain a custom panic() function that cleans those up before calling exit().
Yes, I remember Casey saying that on Handmade Hero. Why waste user's time if what he only wants to do is close the application. I 100% agree with that.

Also, about those other resources you mentioned, do you know if DirectX/COM objects are one of them? I mean, do I need to call ->Release() before exit for each one of them?

I've created another thread asking this here:
https://handmade.network/forums/t...elease_for_each_one_of_them#23901
maverick1013
Yes, I remember Casey saying that on Handmade Hero. Why waste user's time if what he only wants to do is close the application. I 100% agree with that.



if you want an example of that firefox with an unhealthy amount of tabs open takes ages to clean up after itself and shut down all the processes it spawns whereas chrome is much faster. Though I'm not sure how much that is because chrome just kills the tab's processes or has better allocation strategy.
I'd go with option 1, but this is unsafe if object orientation triggers complex code during termination. One way is to have your own memory allocator which doesn't care about complex internal representation nor corrupted reference counting, by just freeing the whole blocks at once if something goes wrong.

I always clean up plain memory and turn down hardware modules cleanly, but worker threads contain executable code and might be waiting for user input or stuck in an infinite loop. If something goes wrong, the program has to terminate quickly but safely. Don't want a sound to keep playing or engine keep running, but waiting for a background thread will only result in not shutting down. A pulse laser might melt itself if kept on for longer than expected. Some hardware ports don't even turn the power off when the computer is turned off, which can cause death or blindness if you have a spotlight with infra-red light or x-rays running while you think it's off.

If you control something dangerous, you must intercept attempts to kill the program from the operating system so that a laser cutter don't keep going after someone tried to turn the horrible thing off during an emergency with burn marks on the walls. There's no standard C++ way to kill threads due to undefined behavior, but one can put a mutex on every action requesting a special resource, and then lock it while turning the resource off and exiting the program.

Edited by Dawoodoz on
That does not make any sense.
It is job of operating system to safely shutdown/stop hardware things working when process dies. You can 100% rely on this, otherwise it is bug in OS (or driver) - but at that point worrying about such bugs all the time is not productive. Otherwise how you would debug your application when you need to terminate it for some reason NULL dereference or other logic bug? What about preemitive OS where you process can take suddenly too much time between two simple operations due to context switch? You cannot expect OS scheduler to know about your lasers. In such cases you simply do not do control process in userspace of preemptive OS. User space processes are safe to kill/terminate in any state.

Edited by Mārtiņš Možeiko on
mmozeiko
That does not make any sense.
It is job of operating system to safely shutdown/stop hardware things working when process dies. You can 100% rely on this, otherwise it is bug in OS (or driver)


If you are not the one building the hardware and writing the driver on kernel level like I do.
You should specify that ahead of time - as nobody else is talking about writing drivers here. Arguments for choosing language/environment in driver is very different from user space application. Also you mentioned abut killing threads in C++ which sounds very strange for writing driver in standard C++.