C/C++ Application closes output stream?

AlexanderProphet

Active Member

Reaction score: 31
Messages: 145

Hi, I noticed this on a Linux machine but I hope the mods won't shoot me down in flames because I imagine it's equally relevant on a FreeBSd or any other Unix. (Im writing a cross platform debugger .)
I was debugging a program ("date" from GNU CoreUtils) and the output suddenly stopped. Examining the source I found
Code:
atexit(close_stdout)
Which is fairly self explanatory. Is this commonly done?
What is it for? I'm guessing it's so that any program reading date's output will see an EOF? Just curious.
Thanks.
 

ralphbsz

Daemon

Reaction score: 1,007
Messages: 1,627

It seems silly. At program exit time, stdout (and all other open file descriptors) will be closed anyway. Doing it with atexit() simply risks doing it too early; there may be some other atexit() function that still needs it.

There is a big nasty hairy error handling question though. Errors on write() don't need to be reported immediately, but can stick around, and be reported on close(). Which is why the close() function does have an error return! So if you use that atexit(close...) idiom, and writing to stdout has previously failed (out of disk space for example), then the error message will get lost. For absolute correctness, what you should do is this: First close all file descriptors other than stderr, and if you get any errors back from close(), then report the errors via stderr. As the last step, close stderr. I think this is what the standard run time library does, but I have honestly not looked at the source code of that startup/shutdown code in decades.
 
OP
OP
AlexanderProphet

AlexanderProphet

Active Member

Reaction score: 31
Messages: 145

It seems silly. At program exit time, stdout (and all other open file descriptors) will be closed anyway. Doing it with atexit() simply risks doing it too early; there may be some other atexit() function that still needs it.
Yes that's pretty much what happened here. My debugger injects a DLL into the child process, and that DLL has a destructor which tries to print some diagnostic data. It turns out atexit functions have priority over destructors.
I fixed it by piping the diagnostic stuff back into the parent so the parent can print it.
And all because some overenthusiastic device tried to tidy up.
Thanks for such a comprehensive answer ralphbsz.
 
Top