[PATCH] support kernels without __ARCH_WANT_SYSCALL_NO_FLAGS

Rich Felker dalias at aerifal.cx
Thu Apr 26 17:17:56 UTC 2012


On Thu, Apr 26, 2012 at 06:56:45PM +0200, Bernhard Reutner-Fischer wrote:
> On 26 April 2012 18:47, Rich Felker <dalias at aerifal.cx> wrote:
> > On Thu, Apr 26, 2012 at 11:00:39AM -0400, Rich Felker wrote:
> >> On Thu, Apr 26, 2012 at 10:18:11AM -0400, Mark Salter wrote:
> >> > +#ifdef __NR_dup2
> >> >  _syscall2(int, dup2, int, oldfd, int, newfd)
> >> > +#elif defined __NR_dup3
> >> > +#include <fcntl.h>
> >> > +
> >> > +int
> >> > +dup2 (int fd, int fd2)
> >> > +{
> >> > +   /* For the degenerate case, check if the fd is valid (by trying to
> >> > +      get the file status flags) and return it, or else return EBADF.  */
> >> > +   if (fd == fd2)
> >> > +           return __libc_fcntl(fd, F_GETFL, 0) < 0 ? -1 : fd;
> >>
> >> Is there a reason this special case is necessary? Not questioning it,
> >> I just want to know.
> >
> > OK, I'll answer my own question: it seems to be a workaround for a
> > kernel bug on 64-bit Linux:
> >
> > http://old.nabble.com/-PATCH--dup2:-Fix-return-value-with-oldfd-%3D%3D-newfd-and-invalid-fd-td23488867.html
> 
> Which, from the looks, was fixed in
> 6c5d0512a091480c9f981162227fdb1c9d70e555 so 2.6.27 and later do not
> need this in libc.

Personally, if I were to put this workaround in musl (my libc), I
would not add the extra code to call fcntl but instead do:

return __syscall_ret((int)__syscall(SYS_dup2, fd1, fd2));

i.e. simply cast to (int) to sign-extend after the raw syscall return
value, but before passing it to my wrapper function that checks if
it's an errno value and sets errno. I don't know what the equivalent
code would be in uClibc, but it's probably a lot smaller and simpler
than adding the extra case to call fcntl. Only problem is it might be
too messy to bypass and re-call the errno-setting code; my syscall
architecture makes it easy but uClibc's might not.

Rich


More information about the uClibc mailing list