This is the mail archive of the libc-ports@sources.redhat.com mailing list for the libc-ports project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH: linux-generic dup2 behaviour


Frankly the kernel behavior in that case seems anti-useful to me.  It's
clear that it was explicitly intended, but I don't know the rationale.
Perhaps you can find some LKML discussion from the time dup3 was
introduced, or raise the subject there to get some clarification.

The rationale I can think of is that dup3(fd,fd,0) seems like it would be a
no-op like dup2(fd,fd) but what actually makes sense is for it to clear
FD_CLOEXEC on fd if it was already set (and likewise to set it if passed),
which perhaps seems odd.  Moreover, there is no robust way to have it act
as a dup2 replacement doing that since the caller doesn't know whether
CLOEXEC was set on the fd or not (and cannot discover it without a race).

So one option would be to change the kernel so dup3(fd,fd,0) is a special
case that acts like dup2(fd,fd), i.e. preserves the CLOEXEC state as it is.
That is an ugly violation of an otherwise straightforward definition of
what the flags argument means.

Another option would be to define some new special flag bit (or value) that
means to set the new descriptor's flags to match the old descriptor's.
Then dup3(oldfd,newfd,O_PRESERVE_FLAGS) is consistent whether oldfd==newfd
or not.

A third option, dup3 could just be changed to reorder its error checks.
That is, preserve its oldfd==newfd => EINVAL case, but diagnose EBADF
first.  Then, libc's dup2 could just call dup3 and in the special case
where it fails with EINVAL but oldfd==newfd, return success.  (For this you
should use the INTERNAL_SYSCALL macros and more fiddling so you don't touch
errno in the EINVAL->success case.)

The only option I see without a kernel change is to make libc's dup2 use a
special case for oldfd==newfd that just does a probe call like fcntl(oldfd,
F_GETFD, 0) for the sole purpose of detecting EBADF.  I suspect kernel
folks will be likely to insist you to do that just so they don't have to
change the kernel.


Thanks,
Roland


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]