Live data from Hacker News

Bugs in Hello World

blog.sunfishcode.online

121–130 of 262 posts

Re: Bugs in Hello World

#121

Seems like PHP does something reasonably right for once! $ php hello.php > /dev/full $ echo $? 255 It doesn't exactly print an error, but at least it returns something non-zero.

Which version are you using? Because mine gives a zero return code. I'm running 7.0.33.

Re: Bugs in Hello World

#122
post #31

Earlier quoted context omitted.

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?

Right — ferror() does not set errno, and so perror() is not appropriate here. fprintf(stderr, ...) would be better.

Re: Bugs in Hello World

#123
A real world example of catching (some, but certainly not all) fflush(), ferror() etc. cases is what "git" does at the end of its execution, the first highlighted line is where it's returning from whatever function implements a built-in ("status", "pull", "log" etc. etc.): :https://github.com/git/git/blob/v2.35.0/git.c#L464-L483

Doing something similar would be a good addition to any non-trivial C program that emits output on stdout and stderr.

In practice I haven't really seen a reason to exhaustively check every write to stdout/stderr as long as standard IO is used, and fflush() etc. is checked.

A much more common pitfall is when dealing with file I/O and forgetting to check the return value of close(). In my experience it's the most common case where code that tries to get it wrong actually gets it wrong, I've even seen code that checked the return value of open(), write() and fsync(), but forgot about the return value of close() before that fsync(). A close() will fail e.g. if the disk is full.

Re: Bugs in Hello World

#124
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…

stdio is program input, and a program's user should be informed about bad inputs. that said, usually, where hello world is usually demonstrated is far away from i/o so perhaps the negligence. but to argue that it's behaving correctly here is unnecessary.

Re: Bugs in Hello World

#125
post #112

Earlier quoted context omitted.

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(10…

That would be the timing aspect of it. You have:

a) a.out writes line 1

b) a.out writes line 2

c) head reads line 1

d) head closes the pipe

We know that b and c both happen after a, and that d happens after c. However, we do not know whether b happens before c, between c and d, or after d. Your a.out process will only get killed by SIGPIPE if it happens after d.

On my system, running a.out under strace is enough to slow it down enough to affect the timing and see the SIGPIPE you were expecting. You may alternatively insert artificial delays in your test program such as by calling the sleep() function between the two lines of output to see the same result.

Re: Bugs in Hello World

#126
post #125

Earlier quoted context omitted.

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(10…

That would be the timing aspect of it. You have: a) a.out writes line 1 b) a.out writes line 2 c) head reads line 1 d) head closes the pipe We know that b and c both happen after a, and that d happens after c. However, we do not know whether b happens before c, between c and d, or after d. Your a.out process will only get killed by SIGPIPE if it happens after d. On my system, running a.out under strace is enough to s…

Sorry, I think I edited my comment while you were replying. But I just noticed the problem in the most recent version was that I didn't write to stdout after the usleep(), so it never raised SIGPIPE. Thanks.

Re: Bugs in Hello World

#127
Correct solution:

  printf '#include \nint main() { return printf("Hello world!\\n") && fflush(stdout); }\n' | cc -xc - && ./a.out > /dev/full && echo "Success\!"

Re: Bugs in Hello World

#128

Earlier quoted context omitted.

> 2. Node.js is not a language. JavaScript is a language, This criticism is the wrong way around. All of the author's "languages" are actually language implementations like NodeJS. You can tell because he produced the results by running the code, rather than by reading a spec.

Yes you are right about the differences. So what I'm proposing is to put JavaScript in the language column (like other languages such as Java) and note the usage of Node.js as the implementation in the second column together with version (similar to Java -> openjdk 11.0.11 2021-04-20). Would that make sense?

That would certainly make sense, but the author hasn't followed that pattern consistently so far - e.g. the row for C doesn't list the compiler or architecture.

Re: Bugs in Hello World

#129
post #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 cal…

But you are forgetting where to print. The classic "Hello World" program requires you to Print to a terminal not to a file. The fact that the terminal and a file can be used interchangeably in *nix system is not the responsibility of the program. Likewise, Printing "hello world" to my 3d printer is not the purpose either. My "hello world" program is meant to Assure the minimum possible feedback that the toolchain is working as expected and being called by your program is not a part of that purpose.

Re: Bugs in Hello World

#130
post #11

It's a good post, but heavily OS dependant. For example, on my Mac: $ ls /dev/null /dev/full ls: /dev/full: No such file or directory /dev/null I guess in theory, you can imitate `/dev/full` by other means.

Yup — I found this worked well: https://www.thedroidsonroids.com/blog/dev-full-osx
Post reply on HN