tags:

views:

90

answers:

4

I have a failing C program, and i've narrowed it down to a fork()ed child trying to close stdout and stderr, which were closed by its parent process before calling fork() - i assume those streams were passed on to the child process.

how can i tell if a stream is closed in C before attempting to close it using something like fclose(stdout)

A: 

If you're working at that level, you probably shouldn't be using the C standard library's buffered FILE pointers (stdin & co), but rather with the underlying file descriptor integers themselves.

You should be able to do some harmless operation, such as maybe a lseek(fd, 0, SEEK_SET) on the file to detect if the underlying descriptor is valid.

unwind
A: 

You can use ftell() to check that. If it returns -1, your stream is mostly closed.

Macmade
A: 

After the call to fclose(), any use of stream results in undefined behavior.

So if it's the FILE* stdout, you can't use stdout anymore at all, not even to check if it's valid/open.

You could use the file descriptor for stdout directly, it's fd 1 .

struct stat stbuf;
if(fstat(1,&stbuf) == -1) {
  if(errno == EBADF) {
    stdout isn't open/valid
  }
}
nos
either im missing something or this doesnt work ?i tried calling fclose() in an added else{} clause (meaning the result of fstat was not -1) and noticed it never closed the stream - even when i was sure it was valid and open
hatchetman82
It does seem unreliable, yes. On my system, what happens is that fclose(stdout); does close the fd. However, for whatever reason, fclose triggers the loading of "/usr/share/nls/nls.alias" , which now gets fd 1 since that's free - and the following fstat succeds - but is now referring to the /usr/share/nls/nls.alias". Things might play out differently if things are called in a different order. Run your program under 'strace' to see what happens. You're better off taking cafs advice, and never close stdin/out/err, but rather redirect them to /dev/null
nos
+2  A: 

C programs on UNIX expect to have a file descriptors 0, 1 and 2 open when they are started. If you do not want them to go anywhere, open /dev/null and dup it to those file descriptors.

caf