News for hackers. Stuff that matters.
Re:Using unwrap() in Rust is okay by jcelerier on Monday August 08, 2022 @01:01PM (#32388078)
> There's either I/O errors - or there's logic errors. A failure with logic should nuke due to the app being in an inconsistent state; trust is lost.

nah. in GUI apps for instance you want the failure in the logic of a sub-sub-function to just tell the error "wops" when the button that triggered the action was clicked, not nuke the app (unless you hate your users). e.g. imagine a 3D software which allows to do mesh operations - user clicks on the "Smooth the mesh" button somewhere. Programmer forgot to handle a division by zero in some degenerate case of the smoothing computation which ends up leading to an exception: a value becomes zero, someone used unsigned integers for n in an "n - 1" computation which ends up in a call to array_of_floats.resize(0xffffffffffffffff) (and a likely std::bad_alloc being thrown if you're in c++).

The original mesh is unchanged as the operation waits until the computation is complete to replace the old mesh with the new.

If you ever decide to crash in this situation I am sure you will have great reviews on 3D modeling software comparisons.

Re:Using unwrap() in Rust is okay by pcwalton on Monday August 08, 2022 @05:16PM (#32391111)
> Programmer forgot to handle a division by zero in some degenerate case of the smoothing computation which ends up leading to an exception: a value becomes zero, someone used unsigned integers for n in an "n - 1" computation which ends up in a call to array_of_floats.resize(0xffffffffffffffff) (and a likely std::bad_alloc being thrown if you're in c++).

To me this is a textbook case of why panic::catch_unwind exists in Rust. Conceptually, the smoothing algorithm failed in an unexpected way, so a panic is appropriate: there is nothing else for the procedure to do but crash. But crashing would be a very poor user experience, because the smoothing operation is conceptually isolated from the application as a whole, so the program shouldn't be affected by a single operation crashing. This is why Rust goes to the trouble to implement unwinding on panic: in certain domains, software fault isolation is important.

Another possibility, of course, would be to spawn a separate process for the smoothing operation, which would effectively replace software fault isolation with hardware fault isolation. But this might be awkward (and slow), which is why few modeling software packages do this.

("A complex smoothing operation in a 3D modeling package fails" is maybe the best example of the need for panic::catch_unwind I've ever heard of--thanks for offering it. I wish I had been able to deploy this example back when we had the debate as to whether catch_unwind should exist at all. Thankfully, we kept it in.) :)

Re:Using unwrap() in Rust is okay by arcticbull on Tuesday August 09, 2022 @02:16AM (#32394759)
> Another possibility, of course, would be to spawn a separate process for the smoothing operation, which would effectively replace software fault isolation with hardware fault isolation. But this might be awkward (and slow), which is why few modeling software packages do this.

I do agree this is a much better model, and it doesn't have to be particularly slow or painful. An example system that does this well is XPC on macOS [1]. The nice thing is by defining a good service model is you can also run your third-party plugins the same way - with full process-level privilege isolation - and in the event of a crash the service can simply be restarted.

[1] https://developer.apple.com/library/archive/documentation/Ma...

Re:Using unwrap() in Rust is okay by Snarwin on Monday August 08, 2022 @06:25PM (#32391896)
The problem with this approach is that, when a panic actually happens at runtime, there is no way to tell whether it was caused by an isolated mistake like forgetting to check for zero, or by memory corruption writing garbage all over your data structures. If it's the first, recovering is fine; if it's the second, you risk exposing the user to data loss and security vulnerabilities. So the only safe thing to do is crash.

Now, it may be true that you get better reviews selling software that corrupts data or gets its users hacked than selling software that crashes. But unless you hate your users, those are probably things you want to avoid.

Re:Using unwrap() in Rust is okay by Tainnor on Tuesday August 09, 2022 @10:06AM (#32398138)
In memory-safe languages, memory is not suddenly corrupted because of some exception that is thrown.

Instead, the bigger issue is corrupt external state, e.g. in a database. But that can of course happen just as well if you panic. What you'll need to do is to wrap your code in a transaction, if possible.

Re:Using unwrap() in Rust is okay by int_19h on Friday August 12, 2022 @12:33AM (#32434740)
Corrupt internal state is just as much of a problem. It doesn't have to be corruption in a sense of garbage memory. It just has to violate invariants - say, one variable got updated, and the other one that depends on it did not.
Re:Using unwrap() in Rust is okay by Tainnor on Friday August 12, 2022 @05:19PM (#32444049)
But that doesn't just happen on its own just because an exception is thrown.

Either you don't handle it and it kills the process, or you handle it at the top level of a web server or similar, and it just kills that request (and that doesn't affect other requests), or you've written explicit error handling logic in which case you've hopefully thought about how to handle the error so as not to carry garbage, inconsistent state around, and hopefully also written some tests for it. This gets even easier if you mostly use immutable data, or at least limit shared state between components.

GGP's original point was that "the only safe thing to do [when encountering an exception] is crash" and for managed-memory-languages that is simply not true.

Re:Using unwrap() in Rust is okay by int_19h on Saturday August 13, 2022 @04:18PM (#32453399)
It happens because a piece of code that was supposed to execute atomically ended up having an exception in the middle - so one assignment did execute, while the other one did not.

If you can well and truly isolate the state that concerns a single request from any other state, then yes, it is safe. The problem is proving that such isolation holds.

Memory-safe or not doesn't actually matter much here.

Re:Using unwrap() in Rust is okay by arcticbull on Monday August 08, 2022 @01:18PM (#32388330)
I would actually want that to crash, yes. That would ensure it gets caught and resolved by developers during development. Or at least increase the odds thereof. Further, if it allocates a few gb, or if it's allocating a large amount of memory because the size parameter got smashed?

If it crashes enough that you'd get terrible reviews it would definitely be caught during development.

If it messes up your mesh silently then you'll definitely still get bad reviews.

And actually having an std::bad_alloc thrown is even worse since you have no idea what state it left things after running some destructors when you weren't planning for it.

Re:Using unwrap() in Rust is okay by jcelerier on Monday August 08, 2022 @01:44PM (#32388649)
> That would ensure it gets caught and resolved by developers during development

i don't know in which reality you live but in mine there's not much relationship between the existence of crashes, and them being resolved during development

> And actually having an std::bad_alloc thrown is even worse since you have no idea what state it left things after running some destructors when you weren't planning for it.

i don't even know what to say. that's the whole point of destructors - you know that things will be unwound in the reverse order from which they were created on automatic storage. that's, like, why c++ exists

Re:Using unwrap() in Rust is okay by arcticbull on Tuesday August 09, 2022 @02:53PM (#32402284)
> i don't know in which reality you live but in mine there's not much relationship between the existence of crashes, and them being resolved during development

Really? Crashes during development are the easiest thing to resolve aren't they? Your debugger gets triggered automatically. In my experience crashes are treated as highest priority.

> i don't even know what to say. that's the whole point of destructors - you know that things will be unwound in the reverse order from which they were created on automatic storage. that's, like, why c++ exists

Have you met my friend the virtual keyword?

Re:Using unwrap() in Rust is okay by jcelerier on Wednesday August 10, 2022 @04:29AM (#32409229)
> Really? Crashes during development are the easiest thing to resolve aren't they?

sure but here we're talking about the edge cases which you won't encounter during development. e.g. imagine you're writing a 3D .obj parser and someone somewhere uses a mesh which for some reason has a NaN instead of a real value somewhere, and your parser parses it and gets a NaN into your system - you'll only encounter the subsequent crashes if your tests had expected such a thing.

now multiply this by infinity - it's impossible to think of everything beforehand. But you really don't want the person to crash their 3D software because of that invalid .obj file, just to show them a pop-up "the mesh could not be loaded" and roll-back to before the loading was attempted.

> Have you met my friend the virtual keyword?

.. what about it ? compilers warn you when you forget it if you aren't using GCC 2.95. https://gcc.godbolt.org/z/d4Yj9z3zf

This hasn't been an issue for more than a decade. clang 3.0 (2011) and gcc 4.1 (2007) already warned for this (and there aren't older compilers on CE that I can test).

There are people who start learning programming today who weren't even born when GCC implemented this FFS

Re:Using unwrap() in Rust is okay by outworlder on Monday August 08, 2022 @05:42PM (#32391435)
Only if you have implemented your destructors correctly. Forgot to add a 'virtual' on one of them? Too bad. Have some pointers to objects? Better remember to call delete on them all. You never really 'know' things are destroyed, that's why tools like Valgrind exist.

The real fun is really the combination with exceptions and destructors. So much so, some projects essentially ban exceptions in C++ code.