1. fche said,

    July 19, 2011 @ 4:06 am

    Interesting UNIX idiosyncrasy!

    “SSH puts its file descriptors 0, 1, and 2 into nonblocking mode, so that it can use select to send data back and forth without blocking”

    Knowing that ssh is used in such nested-process circumstances, perhaps its authors would consider switching to blockable threads instead of file handle flagging.

  2. lev said,

    July 19, 2011 @ 12:14 pm

    It’s not really true that the O_NONBLOCK is attached “to the underlying file”. Ie, if I re-open() the same file in a different process, I won’t inherit the same flags. Rather, in the laguage of susv3, the flags, etc, attach to an “open file description” of which several can refer to the same file, and several “file descriptors” can refer to the same “open file description”.

    Interestingly, CYGWIN applies flags such as O_NONBLOCK to file descriptors, not file descriptions (at least it did last time I checked the source, which was some years ago). I’m not aware of any misbehaviour associated with this breaking of POSIX behaviour.

  3. Ian Lance Taylor said,

    July 19, 2011 @ 2:08 pm

    I was just using language sloppily. When I talk about the underlying file I mean the structure representing the open file within the kernel. Of course opening a new file gets an entirely new set of flags.

    Thanks for the note on cygwin, interesting that it works. I would have thought it would fail on O_APPEND, at least, but perhaps that state is being recorded in the Windows handle somehow.

  4. lev said,

    July 19, 2011 @ 2:56 pm

    I just checked, and it seems the O_APPEND and O_NONBLOCK status are kept with the file descriptor (along with the FD_CLOEXEC, which is supposed to be per-descriptor). This is at least as far as fcntl( …, F_GETFL, …) is concerned — I didn’t check whether the blocking/nonblocking and append/nonappend *behaviour* is set on the underlying open file description, but I’m fairly sure that is not the case.

    Do you have some specific situation where you think this would fail? I’d be interested to test.

  5. Simetrical said,

    July 19, 2011 @ 4:13 pm

    If you have a significant number of readers now, it’s because they liked what you posted before. It doesn’t make sense to change what you post on your blog for fear of alienating people who only came here because they liked what you posted to start with. Apparently people like your idea of random nonsense.

  6. Ian Lance Taylor said,

    July 20, 2011 @ 9:48 pm

    lev: the kind of case where I would check for failure would be
    prog >>foo.txt 2>&1
    where prog writes to both standard output and standard error. On Unix all the output should be appended to foo.txt, because the O_APPEND flag, and, for that matter, the file position, will apply to the underlying file structure referenced by both file descriptors. If the O_APPEND flag does not apply, then it seems possible that prog’s output would overwrite itself.

    If the file position is shared, but the O_APPEND flag is not, then try a program which opens an existing non-empty file with O_APPEND, dups the file descriptor, calls lseek to change the file position to 0, and then write. On Unix O_APPEND means that the file position is reset to the end of the file before each write, and I assume cygwin does the same. The question is whether this also applies to the dup’ed descriptor, as it would on Unix.

  7. lev said,

    July 20, 2011 @ 11:08 pm

    I tested (see below) and cygwin really doesn’t follow Unix. Nevertheless, cygwin has about 2000 packages and *many* users and I’m not aware of any bugs resulting from this misbehaviour. prog >>foo.txt 2>&1 because the dup()d descriptor 2 inherits the append flag from 1 at the time of the dup(). Given the lack of bugs on cygwin, I would suggest that it could be a relatively safe change to make O_APPEND a per-descriptor flag.


    int main(void)
    int f,g;
    f=open(“testfile”, O_RDWR, S_IRUSR | S_IWUSR);
    fcntl(f, F_SETFL, fcntl(f, F_GETFL) | O_APPEND);
    write(g, “x”, 1);

    $ gcc test.c && echo ‘no overwrite plz!’ > testfile && ./a.exe && cat testfile
    xxxoverwrite plz!

RSS feed for comments on this post · TrackBack URI

Leave a Comment

You must be logged in to post a comment.