User: Password:
|
|
Subscribe / Log in / New account

When the programmer is forced to handle return codes

When the programmer is forced to handle return codes

Posted Dec 4, 2009 20:05 UTC (Fri) by magnus (subscriber, #34778)
In reply to: When the programmer is forced to handle return codes by skitching
Parent article: On the importance of return codes

A failed close is usually (always?) a deferred write error, so handle it the same way as if one of the write calls to the file had failed.

If a close would fail after just reading data that would be much more tricky to handle since that would imply that some earlier read data would be incorrect but I don't think that case should occur?

Either way, a failed close shouldn't just go unnoticed. If you can't do anything else, a perror() is better than nothing.


(Log in to post comments)

When the programmer is forced to handle return codes

Posted Dec 4, 2009 20:25 UTC (Fri) by magnus (subscriber, #34778) [Link]

Just checked the man page and noticed that close can also fail with EINTR so a retry loop could be in order.. You learn something new every day...

When the programmer is forced to handle return codes

Posted Dec 4, 2009 22:49 UTC (Fri) by cras (guest, #7000) [Link]

UNIX98 says:

If close() is interrupted by a signal that is to be caught, it will return -1 with errno set to [EINTR] and
the state of fildes is unspecified.

So just looping may not be a good idea either. In any case I'd hope that the only time when close()
could return EINTR is with NFS..

When the programmer is forced to handle return codes

Posted Dec 5, 2009 0:27 UTC (Sat) by nix (subscriber, #2304) [Link]

I suspect that in practice close() can return -EINTR because write() can,
and close() can issue deferred writes. I'd expect a tight loop which
continues until errno != EINTR would work fine: that would drop out on
EBADF as well, which is what you want.

When the programmer is forced to handle return codes

Posted Dec 5, 2009 7:18 UTC (Sat) by cras (guest, #7000) [Link]

Sounds reasonable, yes. But do you think there's a single program that actually is doing the looping,
or even wants to change their code to do this? I've never heard of this being a problem in my code.
And actually I think it's probably better not to do the looping anyway. If you get a signal, it means
someone wants the process to be killed anyway, so might as well get on with it.

When the programmer is forced to handle return codes

Posted Dec 5, 2009 8:00 UTC (Sat) by quotemstr (subscriber, #45331) [Link]

If you get a signal, it means someone wants the process to be killed anyway, so might as well get on with it.
There are many signals, only some of which are meant to kill processes. Consider job control. It's also perfectly legitimate (if a little antiquated) to use signals for reporting and miscellaneous functions. You don't want to leak a file descriptor upon receiving a nonfatal signal.

When the programmer is forced to handle return codes

Posted Dec 5, 2009 21:35 UTC (Sat) by nix (subscriber, #2304) [Link]

I do it in my code because it *has* caused me a problem (notably
getting -EINTR on write()/close() on NFS-served volumes, and
getting -ENOSPC on close()).

(Obviously you actually have helpers that do it. You don't repeat the code
everywhere, that'd be disgusting)

When the programmer is forced to handle return codes

Posted Dec 5, 2009 22:47 UTC (Sat) by cras (guest, #7000) [Link]

So I guess you know what happens in Linux when close() fails with EINTR (with NFS)? It won't close
the fd and it should be retried?

I've gotten rid of alarm()s in (most of) my code and there are no child processes, so I'd think close()s
are pretty safe to do without looping.. And with NFS I first fsync/fdatasync first anyway, so close
probably shouldn't fail anyway. Unless it can fail with EINTR even when it doesn't have to write
anything?.. That would seem almost like a bug.

When the programmer is forced to handle return codes

Posted Dec 6, 2009 0:05 UTC (Sun) by nix (subscriber, #2304) [Link]

So I guess you know what happens in Linux when close() fails with EINTR (with NFS)? It won't close the fd and it should be retried?
The EINTR happens if a signal arrives while pending writes are being flushed. At this point, the FD is not yet closed. (But if it were, you could retry it anyway, and you'd get EBADF and would know that it had been closed last time around.)

Since you have to loop for write()/read() anyway, looping for close() as well is hardly a killer. (And, yes, I would rather that -EINTR would die die die as fast as possible, but unfortunately it is not dead so we have to deal with it.)

When the programmer is forced to handle return codes

Posted Dec 6, 2009 0:29 UTC (Sun) by cras (guest, #7000) [Link]

That also makes me wonder about my fsync/fdatasync calls. I suppose they can also fail with EINTR.
Anyway, as I mentioned above, all signals causing those to my program nowdays should be
external so I don't think I will be doing anything about this problem. (Handling is the same for
EINTR as for EDQUOT/ESPACE.) Interesting to realize it could be a problem, of course.

When the programmer is forced to handle return codes

Posted Dec 6, 2009 11:17 UTC (Sun) by nix (subscriber, #2304) [Link]

POSIX documents that fsync() can return EINTR but does not document it for
fdatasync(). This seems likely to be an oversight to me.

When the programmer is forced to handle return codes

Posted Dec 5, 2009 11:40 UTC (Sat) by hppnq (guest, #14462) [Link]

If the file descriptor is actually gone -- which I think is the case also if close() returns with EINTR -- it may have been reused already in a multi-threaded environment by the time you loop around: you might close the wrong file. In a single-threaded environment, you should expect EBADF immediately after the EINTR, I suppose.

When the programmer is forced to handle return codes

Posted Dec 5, 2009 21:37 UTC (Sat) by nix (subscriber, #2304) [Link]

Yeah, sorry, my attitude about people doing file I/O in many threads at
once is that they deserve everything they get.

I much prefer using processes and explicit IPC to threads.

When the programmer is forced to handle return codes

Posted Dec 6, 2009 11:31 UTC (Sun) by hppnq (guest, #14462) [Link]

I think the point is that close() will always render the file descriptor unusable: if it doesn't you really cannot close() it again safely, because you've bumped into a kernel bug.

When the programmer is forced to handle return codes

Posted Dec 7, 2009 23:02 UTC (Mon) by cventers (guest, #31465) [Link]

Multithreaded programs might reallocate the fd before your thread got the opportunity to see an EBADF. If you broke the loop on success as well, you'd be mostly okay, except for the unspecified status of the fd as per UNIX 98...


Copyright © 2017, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds