0

I am filled with questions pertaining to the situations where a desktop-application hangs, possibly for minutes.

I've got this complicated game-engine written in c++. Several times during development, I've accidentally found an infinite loop during testing and the program causes the entire system to hang, usually for a few minutes. I used to just restart my computer with the physical button, because I didn't realize it was so bad. I'm using Linux (Ubuntu, Debian), is it any better on Windows or Mac?

Am I responsible for damage to a user's installation-environment or the loss of data if they restart their computer while my software is hanging, and their OS becomes unusable? Of-course, I can test the software loads and be quite confident that it doesn't happen, but I don't know if I can be 100% sure.

Is there some clever way overall, to stop a program from hanging and stealing all of the CPU for itself? Like, lowering my game's priority to the kernel?

If the game has a feature for users to create and share maps, which can include writing scripts sent to the engine's interpreter, there would be tons of ways for them to spawn way too many entities and enable their AI that I'm quite sure they could make the program hang. I'm not sure I can enforce every countermeasure against that kind of mess, especially from the game's release. Am I responsible if someone makes a map that damages someone's installation?

I really hope I'm overthinking this. Is there an easy way to protect my program from hanging? Do processes made by visual-studio-code have worse problems with hanging for development-purposes? Is my kernel mysteriously bad at stopping hanging processes?

I don't need help removing infinite-loops from my code, the concern is that due to its complexity I would miss one.

5
  • 2
    "I don't need help removing infinite-loops from my code" - strong disagreement there. That's your main problem. Jan 23, 2022 at 0:20
  • Maybe. Are infinite-loops the only source of dangerous hanging? If that were true, I would agree. I just know so little about it.
    – SilverRain
    Jan 23, 2022 at 0:37
  • 3
    @SilverRain Thats your real problem. Your dealing with an issue you don't really understand and by the sound of it are scared of. This is a very broad area with a huge spectrum of options. Jan 23, 2022 at 1:44
  • 1
    The problem is not removing infinite loops, the problem is finding them so they can be removed. But that's not the only way a program can hang anyway.
    – user10489
    Jan 23, 2022 at 6:23
  • 2
    "Am I responsible for damage to a user's installation-environment or the loss of data if they restart their computer while my software is hanging, and their OS becomes unusable?" — if you are, then I'd like to have a talk with Bill Gates about the last 30 years of Windows updates. Jan 23, 2022 at 18:36

2 Answers 2

3

Theoretically, it is the responsibility of the OS to stop any single application from impacting the rest of the system through resource starvation. However, this is a complicated problem and as you have discovered, there are numerous failure cases. The OS should at least be able to minimize the chance of any permanent damage. As such most modern OSes in a general user context work on a mutual respect principle: The application does its best not to consume excessive resources, and the OS does its best to share the resources available among the applications to prevent issues like stalls.

However, the OS can't do anything to prevent intraprocess stalls, where tasks within an process block on logical constructs that make your application feel like its hanging. For example your game loop not delivering new frames. What the OS can do in that situation is provide mechanisms to allow the user to exit the application in that situation. Have you ever tried alt+tab whilst your application was hanging?

So long as you control the development process of the code, and put in reasonable limits on your system (for the custom maps example, put a limit on how many entities can be in a map), and then effectively test the system at those limits, you should be able to avoid these issues. (You may wish to provide ways to override these limits with suitable warnings as more powerful computers become available).

However, if you wish to load external code, that is where it gets into the complex topic of sandboxing. This is a broad and complex topic with many subtleties. It would be best to start from an examination of what your users expect from code not explicitly part of you system. In a lot of cases (game mods), it is entirely at the users responsibility. In other cases such as web browsers, there is an expectation that the browser will provide a significant measure of protection, and as such most modern browsers run in multiple processes allowing more granular use of OS protection mechanisms.

3
  • Thanks for the answer! If I alt-tab in those moments, generally it won't work, unless it was very early. The best thing for me to do is press the X-button and wait a few a minutes and that usually works.
    – SilverRain
    Jan 23, 2022 at 2:12
  • 1
    Personally, I have found linux is perticuarly bad with this issue due to the amount of the GUI that runs as plain userspace processes. Switching virtual console can sometimes help, but not always. Jan 23, 2022 at 2:15
  • 1
    Mild anecdote about sandboxing that I didn't think is important for the answer: A couple of years ago I ran into an issue where oracle java <=8 JREs with heavily loaded GCs running inside a linux cgroup cpu quota of less than 10% of the total core count of the system would experience >90ms lag spikes on the JRE, and ~10ms lag spikes across everything else on the system, due to an interaction between JRE GC thread count choices and how the linux cgroup handled cpu usage limitations. Sandboxing gets very complicated. Jan 23, 2022 at 2:17
2

Perhaps a list of possible ways a program can hang itself and/or the system would help:

  • CPU overload -- but usually the OS gives other things time slices too, unless you have grabbed real time priority
  • memory overload -- swap can make this better or worse (usually worse); mitigation is to tune your OOM killer or restrict memory use with ulimits or cgroups
  • Disk overload -- if your app uses so much disk I/O that other applications are stuck waiting; this can be combined with a memory issue to cause thrashing, which doesn't truely lock up your computer but certainly makes it feel that way and may not be practically recoverable
  • Input device lockup -- if your application grabs keyboard and mouse and then hangs, there may not be a way to recover without an out of band input (like ssh from another terminal or kernel SAK. Kernel SAK is usually disabled by default for security reasons, and its actions are typically overkill anyway, so this is the worst solution.)
  • GPU overload or crash -- it is possible to overload the gpu so that it becomes slow or seemingly unresponsive. Sometimes it is possible to trigger bugs in the gpu driver that causes a display lockup or crash. This may or may not lock up the rest of the system; if it does, there is no recovery except to reset. If it doesn't, the only recovery may be to ssh in and reboot, and even then sometimes a power cycle is required after shutdown.

I'm sure there's others I've missed.

If your application itself is locking up, it may be possible to add a watchdog within the application to either try to clean things up, or maybe in debug mode, abort completely.

Another mitigation for infinite loops within the application is to design to detect them or allow them. To detect them, in a code section that it is possible to have a stuck loop, leave a hook for a watch dog timer or countdown timer and abort the loop when it triggers. To allow them, either treat the loop as an event, and for the next iteration, have it add itself back to the event queue; or add yields within the possible infinite loop to allow it to be postponed or aborted.

4
  • Yes, I have such measures for avoiding infinite loops in AI-code. What s that about the "watchdog"? That seems interesting. I am assuming in this case that this is a case of my application locking itself up. It should be CPU-overloading in the case of infinite loops.
    – SilverRain
    Jan 23, 2022 at 22:51
  • 1
    A watchdog timer counts down and when it hits zero, it resets something. The application, to avoid being reset, should kick the timer periodically so that the timer starts over at its original value rather than reaching zero. When the application has locked up, it will fail to reset the timer. Smaller timers might put a limit on the number of times a loop iterates or how long it iterates and abort the loop rather than the whole application.
    – user10489
    Jan 23, 2022 at 23:41
  • Is it used in these cases? I infer that if the kernel can't (instantly) stop a program when a user presses the x-out-button on the application's window-frame, having it done automatically wouldn't be stronger. I might have to research how the x-out-button works, because it probably isn't xkill on linux.
    – SilverRain
    Jan 25, 2022 at 17:07
  • You could write a watchdog into your application or a companion process. The kernel can have a hardware watchdog that resets the whole machine. The graphical interface (gnome, others) has its own watchdog timers that will ask the user if they want to kill an unresponsive app. The close button in the window sends a close message to the app. If the app ignores it, the window manager can close the application's X11 connection to the GUI which may cause the application to get an I/O error next time it tries to update the GUI, or the application may not ever exit and continue headless.
    – user10489
    Jan 25, 2022 at 23:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.