Live data from Hacker News

Bugs in Hello World

blog.sunfishcode.online

111–120 of 262 posts

Re: Bugs in Hello World

#111

Even Golang de facto suffers from this. I don't think I can name a time I saw someone check the return value of fmt.Print or log.Print. Not checking the return value still seems the the "right" thing to do.

Indeed, first result and no error checking:

https://gobyexample.com/hello-world

Re: Bugs in Hello World

#112
post #95

Earlier quoted context omitted.

> This isn't just about the filesystem being full btw. If you imagine a command like ./foo.py | head -n 10, it only makes sense for the 'head' command to close the pipe when it's done, and foo.py should be able to detect this and stop printing any more output. The usual way of handling this is by not (explicitly) handling it. Writes to a closed pipe are special, they do not normally fail with a status that the progra…

That would be at best a Linux extension, not some general C behavior you can assume when writing your program. That said though, I can't even reproduce what you're saying on Linux: printf '%s\n' '#include ' 'int main() { setvbuf(stdout, NULL, _IONBF, 0); int r = fputs("Starting\n", stdout); fflush(stdout); fprintf(stderr, "%d\n", r); }' | cc -x c - && ./a.out >&- // Prints '0' instead of dying

That's a POSIX thing. It doesn't apply to all C implementations but it does apply to many more than just Linux-based ones. You've not got a closed pipe so you wouldn't see it, you've just got a closed file descriptor. Try running it as

  ./a.out | :
and you will probably see it. I say probably because there is a timing aspect as well, the write may happen before the pipe gets closed in which case it will not fail, but it is unlikely to.

Re: Bugs in Hello World

#113

> There's our "No space" error getting reported by the OS, but no matter, the program silently swallows it and returns 0, the code for success. That's a bug! Bzzt, no. You can't say that without knowing what the program's requirements are. Blindly "fixing" a program to indicate failure due to not being able to write to standard output could break something. Maybe the output is just a diagnostic that's not important,…

> Also, if a program produces output with a well-defined syntax, then the termination status may be superfluous; the truncation of the output can be detected by virtue of that syntax being incomplete.

The author covers this (or rather, the possibility that truncation can not be detected).

Re: Bugs in Hello World

#114

It's only a bug if the requirements are: "Print Hello World and indicate if it succeed or not" If the requirements were: "Print Hello World, then return 0" It's working as intended. I'd even go so far as to say that print(); return 0; should always return 0, it would be weird for such a program to ever return anything other than 0 (where would that return come from?).

The requirement of a "Hello World" program is always, by nature, to print "Hello World".

If my program calls your Hello World program, it expects it to print Hello World. That's basically the point of the program.

If your program don't print Hello World for whatever reason, of course you don't need to manage the error if it wasn't specified. But it's probably a bad thing (call it a bug or not) to exit 0 which the caller will interpret by "Hello World have just been printed successfully", I can go on and print ", John".

I agree it's probably not going to be in the requirements, and world will probably not collapse if you don't manage the error, but it's with no doubt an idiom required by most OSes to ensure programs are normally working.

You can also create orphan processes if it's needed by your requirements, but it's probably a bug or a hole in your requirements. Because at some point, non idiomatic programs will be used in situations where they will be creating issues. And we are talking about issues that are very hard to even spot.

Those "non requirements" are exactly how you lately discover that you have no logs from the last two weeks or that your backups aren't complete.

It's not requirement, but it's just hygiene.

tbf, I'm arguing of what should be an idea world, but I probably have myself written those sorts of bugs. Writing idiomatic code is hard and no one is to blame for not doing it perfectly. I just think it's some ideal to aim for.

Re: Bugs in Hello World

#115
post #45

Earlier quoted context omitted.

The bug is not that the program failed, it's that the program failed but reported a success.

Failure isn't defined by programmed control structures, it's defined by requirements and implemented via programming. If the requirements of a hello world program include accounting for all error boundaries of the host system, then I am yet to see them written down but would invite anyone to provide them. The parent comment has made a start in this regard.

every program is given the 3 stdio channels: stdin, stdout, stderr. if the program is unable to use any of these as expected, it's an error that should be reported back to the user. today it's /dev/full but tomorrow it could be a log file with wrong access perms. you don't want to be returning 2 weeks later to find out that nothing was written, and your program didn't complain.

Re: Bugs in Hello World

#116
post #112

Earlier quoted context omitted.

That would be at best a Linux extension, not some general C behavior you can assume when writing your program. That said though, I can't even reproduce what you're saying on Linux: printf '%s\n' '#include ' 'int main() { setvbuf(stdout, NULL, _IONBF, 0); int r = fputs("Starting\n", stdout); fflush(stdout); fprintf(stderr, "%d\n", r); }' | cc -x c - && ./a.out >&- // Prints '0' instead of dying

That's a POSIX thing. It doesn't apply to all C implementations but it does apply to many more than just Linux-based ones. You've not got a closed pipe so you wouldn't see it, you've just got a closed file descriptor. Try running it as ./a.out | : and you will probably see it. I say probably because there is a timing aspect as well, the write may happen before the pipe gets closed in which case it will not fail, but…

Yeah I should've said POSIX, my bad. But yeah my point was it's not plain C behavior.

And yes on Linux I do see it with your no-op example now. Though for some reason not with 'head'... what's going on? Is it not closing the pipe when it exits?

  $ printf '%s\n' '#include ' '#include ' 'int main() { setvbuf(stdout, NULL, _IONBF, 0); int r = puts("Starting...\n"); r += fputs("First\n", stdout); fflush(stdout); usleep(1000000); fprintf(stderr, "%d\n", r); }' | cc -x c - && ./a.out | head -n 1
  Starting...
  19
Edit: D'oh, see below.

Re: Bugs in Hello World

#117
post #31

This raises an interesting question: is there any IO function that should return unit/void? Or equivalently are there any IO functions for which we can safely ignore the return value/ignore all exceptions? It seems like every single IO thing I can think of can have a relevant error, regardless of whether it's file-system related, network, or anything else.

In C, and many other languages, the file stream error state is saved after each operation, so you can skip error checking on every output line and only do if (fflush(stdout) != 0 || ferror(stdout) != 0) { perror("stdout"); return EXIT_FAILURE; } at the end of the program. The same should be done for stderr as well. In GNU programs you can use atexit(close_stdout) to do this automatically.

Would perror() return the first/oldest error or the last?

Re: Bugs in Hello World

#119
post #73
post #32

I’m disappointed. I expected some obscure edgecase (like “Main is usually a function…” [1]) but instead that’s about scope handling, contract design and responsibility shift. “Hello world” method simply calls an API to a text interface. It uses simple call, to a simple interface that is expected to be ever present. I don’t find any bug there. It won’t work if such interface isn’t available, is blocked or doesn’t exis…

I found it interesting. If you generalize a bit, the question is "Will a naively written stdio program handle IO errors?". The fact that for several popular languages the answer is "no" is disappointing.

To me it was less disappointing and more intriguing.

Re: Bugs in Hello World

#120
post #45
post #32

I’m disappointed. I expected some obscure edgecase (like “Main is usually a function…” [1]) but instead that’s about scope handling, contract design and responsibility shift. “Hello world” method simply calls an API to a text interface. It uses simple call, to a simple interface that is expected to be ever present. I don’t find any bug there. It won’t work if such interface isn’t available, is blocked or doesn’t exis…

The bug is not that the program failed, it's that the program failed but reported a success.

Whether the program fails or not, is a matter of specification.

    printf("Hello, World!\n")
Is me saying: "Do a write syscall to stdout. I don't care what the return value is, I don't care if the flush is successfull if stdout happens to be buffered." If that is what I want to do, aka. what the program is specified to do, then it didn't fail.
Post reply on HN