Hacker News new | ask | show | jobs
by _ph_ 2162 days ago
Programming errors happen, but thats why I don't get, that companies still use programming languages, where such errors result in a crash vs. an error which can be handled and recovered from. A faulty XML file shouldn't render the whole machine unusable.
6 comments

Not sure if the language is at play, you can write shitty software in any language
Yes, you can create a mess in any language. However, a lot of languages protect you against a lot of potential mistakes and also give you means of safely recovering from errors. The XML parser might not be better when written in another language, but if it is called from within an error handler, the calling program could recover from the error.
What language makes it impossible to write if parse(config) == false then reboot?
In this case the XML file parsed fine, but the contents (specifically an empty element that the firmware expected to be populated) caused a crash.
I guess I should rephrase. What language makes it impossible to call abort() after a required XML element is found to be missing?
Presumably languages which default to optional instead of null with the default ergonomics being to “or_else” instead of “unwrap” will encourage safer error handling.

It works for me, but I don’t know if it is yet well known what the effect of developer UX on error rate is.

Nope, you are still not making sense. Just look at the "Facebook remotely disables all apps" issue. Both times it was issues deserializing - the deserialization wasn't unsafe or outright crashing, it was simply the SDK wasn't prepared to deal with the data it got.
I find that I can write code that is less likely to crash or fail more easily in some languages than in others. If this is not the case for you, I understand that it isn't compelling but that's okay. Not particularly looking for you to adopt anything.

UX things in some languages guide me to idiomatic code that is safer. And as engineers, we know there is no guarantee, only shades of improvement. But again, if language choice does not affect your program quality, so be it.

Impossible is a big word :). But while a C or C++ program tends to crash in the presence of an error, like with a segfault, a lot of languages just throw an error which you can catch. So you could proceed with the default values, if the file cannot be read correctly.
"can catch" doesn't give you anything, unless you actually do the catching.

C and C++ programs tend to crash in the presence of an error, but so do rust programs (panic), C# and java and js and python programs (unhandled exception). Some languages make it harder to footgun yourself for certain types of errors, but never all types of errors.

I have seen js programs (and similar stuff in other languages) crash because of something like

    JSON.parse(response).list[0].string.length
where the response was valid json, just the .list property was an empty array (or even undefined because omitted in the json).

Does rust protect from such mistakes (because I know some people on here like to claim rust is the answer to everything)? Verbatim from their docs:

    let v = vec![0, 2, 4, 6];
    println!("{}", v[6]); // it will panic!
I'd guess it's exactly such type of bounds error at play with the Saumsung thing, from the mention of that empty <list/> element in the article.

I have written such code myself because I was lazy or distracted or "need performance" or "this can never be empty per spec" or "oops, my range calculation was off by one", tho luckily I didn't outright brick anything, yet.

There is one difference in Rust: they are so confident of their memory model, panic!() only kills the current thread. The exception is if it happens in the main thread it kills everything.

In Samsung's case, if they put the parsing of the telemetry config xml file in a separate thread the default Rust behaviour is not to kill the entire thing. Sending the telemetry back to servers sounds like something you would do in a separate thread, so perhaps it would have saved them.

Other languages with similarity strong memory models like Java / Python / Haskell could do the same thing of course. And in those languages programmer could just emulate it in any case. C / C++ with their weak memory models could not sanely do it. A programmer could emulate it in those languages by using separate processes if the OS supported it, but they would have to forgo shared memory.

Not a huge difference perhaps - but Rust's strong memory model does buy you something.

Oh please. C and C++ programs can be coded to fail gracefully and "a lot of languages" fail in unpredictable and unfortunate ways and shitty programmers still don't catch those magic errors. This is a matter of crappy engineering, not per se crappy language.
You can have programs crash in any language. However, it is the question, how well a program can recover from an error. Having a concept of error handlers in the language, which can catch conditions occuring inside the code they are calling, leads to more robust programmers. Think of it as airbags and seat belts. Drivers, who don't make a mistake, wouldn't need them, but in reality shit happens, and they give us more survival chances.
if !parse(config) then reboot. Please, for the love of God.
I’m sorry but I find ruby „reboot unless config.parse?” much more readable here.
You can argue about which syntax is best. But irrespective, having a perfectly good boolean already, but then comparing it to true or false to unnecessarily create another boolean is always just wrong.
Whether it's an Exception or a segfault, the application still crashes because its input is in a bad state. This class of problem is not restricted to memory-unsafe languages.
> still use programming languages, where such errors result in

Unfortunately no language or other framework or system can completely do away with programming logic errors.

But that is the point I was trying to make. No language can save you from logic errors, but a lot of languages let you recover from errors in functions. The simplest way is exception handling in Java like try { parse(xmlFile) } catch ( ... ) {.... } There is no reason the device should get in an undefined state if parsing that file fails or even completely crash.
> There is no reason the device should get in an undefined state

That is impossible to guarantee. It isn't even possible to completely generally[†] test for - what you have there is a variant of the halting problem (https://en.wikipedia.org/wiki/Halting_problem).

[†] added "generically" there as it is possible, using formal methods from the start, to prove that a program is correct so will not error (in an unexpected manner) on any input, but such methods are time-consuming so outside of certain specific fields you'll not find them used

But not having a `try...catch` for such events is a kind of logic error.

The choice of programming language only gets you so far - it's up to the developers to actually handle errors in a meaningful way.

I'd argue that languages which force handling via the type system (e.g. `Result<T, Error>` in Rust) makes it less likely that bugs like this will go unhandled, since the position if the programmer does not explicitly opt out of error handling (with `unwrap` etc) is a compilation error rather than missing error handling.
What specifically goes in the catch block? Please be precise.
In the case of an appliance device where the XML file was externally supplied? Continue as though the file never existed (and possibly also delete the XML file).
Either proceed with some safe default values or at least go into a maintenance mode, where the file can be replaced or newly downloaded.
This seems more like a process / testing issue. Someone should've tested this update, at least once, before it was deployed to the public, right?

(I used to work at a company where people checked in code, asked someone else to test it, and it was clear it had never even been run!)

If they had used Rust, this whole thing could have been avoided!