I am new to Rust and have come to understand Rust defaults to panics and not exceptions.
I have a rust project that depends on external libraries.
I have handled all unwraps and ?'s in my code using match statements, but I am not sure how to handle a panic by external libraries.
In other languages I would just catch an exception thrown by the library.
As Rust defaults to panics, the libraries don't return an exception but panic and thus abort execution of the thread.
I would ideally want to log and continue execution, not panic and abort.
I have tried the following:
catch_unwind, but this looks like something I can't use on an external library.
log-panics crate, which logs the panic using a panic hook. I am able to log the panic, but not prevent aborts.
DON'T PANIC
I mean, that's the real solution: you must avoid panics, not try to recover from them when they happen.
Some languages casually use exceptions to deal with conditions preventing some operations, and manage them without crashing.
In Rust, those unsupported conditions are managed with errors, not panics.
A panic in Rust is
most often a bug, usually temporary because you've put an unwrap in your first prototyping
or a very extraordinary condition
As the Book says:
When code panics, there’s no way to recover
The various utilities like catch_unwind are, at best, aiming at more gracefully quitting, they don't let your program run as if nobody happened.
When a crate you use panics, first check you're using the function as expected (and if you can't check that without panicking that's a bug in that lib), then either have it fixed or fix it yourself if you can.
There's no reasonable way to deal with a casual panic, apart from crashing as fast as possible. A panic isn't casual in the life of your program.
Related
With a snippet like
perl6 -e 'loop { FIRST say "foo"; last }'
I get
WARNINGS for -e:
Useless use of LOOP_BLOCK_1 symbol in sink context (line 1)
foo
I know how to work around the warning. I'm wondering about what the source of the warning is. I found this open ticket, but it doesn't seem to have received any attention.
What is this warning about?
And what about this is useless?
Version
$ perl6 --version
This is Rakudo version 2018.06 built on MoarVM version 2018.06
implementing Perl 6.c.
It's a bug, a bogus warning.
I know how to work around the warning.
That's the main thing.
I'm wondering about what the source of the warning is.
It's a bogus warning from the compiler.
I found this open ticket, but it doesn't seem to have received any attention.
I think it got some attention.
bbkr, who filed the bug, linked to another bug in which they showed their workaround. (It's not adding do but rather removing the FIRST phaser and putting the associated statement outside of the loop just before it.)
If you follow the other links in bbkr's original bug you'll arrive at another bug explaining that the general "unwanted" mechanism needs to be cleaned up. I imagine available round tuits are focused on bigger fish such as this overall mechanism.
Hopefully you can see that it's just a bizarre warning message and a minor nuisance in the bigger scheme of things. It appears to come up if you use the FIRST phaser in a loop construct. It's got the very obvious work around which you presumably know and bbkr showed.
What is this warning about?
Many languages allow you to mix procedural and functional paradigms. Procedural code is run for its side effects. Functional code for its result. Some constructs can do both.
But what if you use a construct that's normally used with the intent of its result being used, and the compiler knows that, but it also knows it's been used in a context in which its value will be ignored?
Perls call this "useless use of ... in sink context" and generally warn the coder about it. ("sink" is an alternative/traditional term for what is often called "void" context in other language cultures.)
This error message is one of these warnings, albeit a bogus one.
And what about this is useless?
Nothing.
The related compiler warning mechanism has gotten confused.
The "Useless use of ... in sink context" part of the message is generic and hopefully self-explanatory.
But there's no way it should be saying things like "LOOP_BLOCK_1 symbol". That's internal mumbo-jumbo.
It's a warning message bug.
Panic! seems to be the right way to stop a program while in development mode. But one should not ship a program that displays such a message for an excepted error:
thread '<main>' panicked at 'error message: ()', x.rs:785
Is there any way to exit a program early with an error code, without displaying developer oriented text? I could use process::exit but I've read that it does not perform cleanup, so what should we use?
panic! is not the right way to stop a program.
Its sole purpose is to abort when everything is about to go south and you have no way to recover. If you are expecting some wrong behaviour anywhere, use Result and recover from that behaviour by printing a nice message and cleanly exiting.
If you have panic!s or assert!ions in your code and they trigger, the message you showed is the only correct thing that should be displayed, because it's a bug in your code and there's no clean way to recover from a bug.
Note that panic! does not necessarily perform cleanup. If you panic, and another panic happens in a Drop impl, the program simply aborts. Also there's a setting for rustc that turns off the cleanup on panic and simply aborts on the panic!.
I am evaluating different multiprocessing libraries for a fault tolerant application. I basically need any process to be allowed to crash without stopping the whole application.
I can do it using the fork() system call. The limit here is that the process can be created on the same machine, only.
Can I do the same with MPI? If a process created with MPI crashes, can the parent process keep running and eventually create a new process?
Is there any alternative (possibly multiplatform and open source) library to get the same result?
As reported here, MPI 4.0 will have support for fault tolerance.
If you want collectives, you're going to have to wait for MPI-3.something (as High Performance Mark and Hristo Illev suggest)
If you can live with point-to-point, and you are a patient person willing to raise a bunch of bug reports against your MPI implementation, you can try the following:
disable the default MPI error handler
carefully check every single return code from your MPI programs
keep track in your application which ranks are up and which are down. Oh, and when they go down they can never get back. but you're unable to use collectives anyway (see my opening statement), so that's not a huge deal, right?
Here's an old paper (back when Bill still worked at Argonne. I think it's from 2003):
http://www.mcs.anl.gov/~lusk/papers/fault-tolerance.pdf . It lays out the kinds of fault tolerant things one can do in MPI. Perhaps such a "constrained MPI" might still work for your needs.
If you're willing to go for something research quality, there's two implementations of a potential fault tolerance chapter for a future version of MPI (MPI-4?). The proposal is called User Level Failure Mitigation. There's an experimental version in MPICH 3.2a2 and a branch of Open MPI that also provides the interfaces. Both are far from production quality, but you're welcome to try them out. Just know that since this isn't in the MPI Standard, the function prefixes are not MPI_*. For MPICH, they're MPIX_*, for the Open MPI branch, they're OMPI_* (though I believe they'll be changing theirs to be MPIX_* soon as well.
As Rob Latham mentioned, there will be lots of work you'll need to do within your app to handle failures, though you don't necessarily have to check all of your return codes. You can/should use MPI error handlers as a callback function to simplify things. There's information/examples in the spec available along with the Open MPI branch.
My program runs for about 10 hours during the night, sometimes I wake up to see that it has crashed (for whatever reason). It is usually a "Program Name" has stopped working, and the only button there is to close the program. I have tried watching and waiting for it to crash but the problem seems very hard to reproduce (and I can't watch it 24/7). I have used try and catch statements in my program in potentially problematic areas and told the program to dump to a text file if it catches an exception. But this isn't good enough it seems.
TLDR: Is it possible to tell my program to run a particular function when an exception has been detected in the program in general (without specifics) so that I can dump the stacktrace to a text file and investigate later?
Is it possible to tell my program to run a particular function when an exception has been detected...
Yes, but the specifics depend on the platform that you are using:
If you have a Console application, put a big Try ... Catch around Sub Main.
If you use WPF, add an event handler to AppDomain's or Dispatcher's UnhandledException event. Specifics can be found in the following question:
WPF global exception handler
In you use WinForms, you can also wrap Sub Main (which might be auto-generated) or attach to AppDomain.UnhandledException, see here for details:
WinForms Global Exception Handling?
For completeness, global exception handling in web applications is done in global.asax's Application_Error method:
How to catch unhandled exceptions in an asp.net application?
It's generally not a good idea to do this. You could, however, look at AppDomain.UnhandledException. This is pretty much restricted to one domain, and you'll also receive (potentially) notifications for all unhandled exceptions unrelated to your program.
This is usually used for class libraries, but I think with a bit of fiddle, you might get it to work.
Options:
1) When there is bad input, the app crashes and prints a message to the console saying what happened
2) When there is bad input, the app throws away the input and continues on as if nothing happened (though nothing the problem in a separate log file).
While 2 may seem like the obvious solution, the app is an engine and framework for game development, so if a user is writing something and does something wrong, it may be beneficial for that problem to be immediately obvious (app crashing) rather than it being ignored and the user potentially forgetting to check the log to see if there were any problems (may forget if the programmed behavior isn't very noticeable on screen, so he doesn't catch that it is missing).
There is no one-size-fits-all solution. It really depends on the situation and how bad the input is.
However, since you specifically mentioned this is for an engine or framework, then I would say it should never crash. It should raise exceptions or provide notable return codes or whatever is relevant for your environment, and then the application developer using your framework can decide how to handle. The framework itself should not make this decision for all apps that utilize the framework.
I would use exceptions if the language you are using allows them..
Since your framework will be used by other developers you shouldn't really constraint any approach, you should let the developers catch your exception (or errors) and manage what to do..
Generally speaking nothing should crash on user input. Whether the app can continue with the error logged or stop right there is something that is useful to be able to configure.
If it's too easy to ignore errors, people will just do so, instead of fixing them. On the other hand, sometimes an error is not something you can fix, or it's totally unrelated to what you're working on, and it's holding up your current task. So it depends a bit on who the user is.
Logging libraries often let you switch logs on and off by module and severity. It might be that you want something similar, to let users configure the "stop on error" behaviour for certain modules or only when above a certain level of severity.
Personally I would avoid the crash approach and opt for (2) that said make sure that the error is detected and logged and above all avoid any swallowing of errors (e.g. empty catch).
It is always helpful to have some kind of tracing/logging module, for instance later when you are doing performance tuning or general troubleshooting.
It depends on what the problem is. When I'm programming and writing error handling I use this as my mantra:
Is this exception really exceptional?
Meaning, is the error in input or whatever condition is "not normal" recoverable? In the case of a game, a File not Found exception on a texture could be recoverable and you could show a default texture so you know something broke.
However, if you have textures in a compressed file and you keep getting checksum errors, that would be an exceptional exception and I would crash the game with the details.
It really boils down to: can the application keep running without issue?
The one exception to this rule though (ha ha) is, if something is corrupted you can no longer trust your validation methods and you should crash as quickly as you can to prevent the corruption from spreading.