On Tue, Jun 19, 2012 at 02:02:03PM -0700, Philip Guenther wrote:
> On Tue, Jun 19, 2012 at 1:26 AM, Paul Irofti <p...@irofti.net> wrote:
> > The newer glibc's, when creating a socket, add some higher bit flags to
> > the type argument that are used for debug, statistics, profiling
> > whatever. They are not useful and implementation specific.
> 
> Aren't those SOCK_CLOEXEC and SOCK_NONBLOCK?  I would expect ignoring
> the former to result in rapid fd leaks, and ignoring of the latter to
> result in code blocking unexpectedly...

Thanks once again. How about this:

Index: linux_socket.c
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_socket.c,v
retrieving revision 1.45
diff -u -p -r1.45 linux_socket.c
--- linux_socket.c      19 Jun 2012 11:28:20 -0000      1.45
+++ linux_socket.c      20 Jun 2012 11:23:44 -0000
@@ -239,17 +239,50 @@ linux_socket(p, v, retval)
        } */ *uap = v;
        struct linux_socket_args lsa;
        struct sys_socket_args bsa;
-       int error;
+       struct sys_fcntl_args bfa;
+       struct sys_close_args bca;
+       int error, type_flags, fd;
 
        if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
                return error;
 
+       type_flags = lsa.type & ~LINUX_SOCKET_TYPE_MASK;
+       if (type_flags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK))
+               return EINVAL;
+
        SCARG(&bsa, protocol) = lsa.protocol;
        SCARG(&bsa, type) = lsa.type & LINUX_SOCKET_TYPE_MASK;
        SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
        if (SCARG(&bsa, domain) == -1)
                return EINVAL;
-       return sys_socket(p, &bsa, retval);
+       error = sys_socket(p, &bsa, retval);
+       if (error)
+               return error;
+       
+       fd = SCARG(&bfa, fd) = retval[0];
+       if (type_flags & LINUX_SOCK_NONBLOCK) {
+               SCARG(&bfa, cmd) = F_SETFL;
+               SCARG(&bfa, arg) = (void *)O_NONBLOCK;
+               error = sys_fcntl(p, &bfa, retval);
+               if (error)
+                       goto err;
+       }
+
+       if (type_flags & LINUX_SOCK_CLOEXEC) {
+               SCARG(&bfa, cmd) = F_SETFD;
+               SCARG(&bfa, arg) = (void *)FD_CLOEXEC;
+               error = sys_fcntl(p, &bfa, retval);
+               if (error)
+                       goto err;
+       }
+       retval[0] = fd;
+       return error;
+
+err:
+       SCARG(&bca, fd) = fd;
+       sys_close(p, &bca, retval);
+       retval[0] = -1;
+       return error;
 }
 
 int
Index: linux_socket.h
===================================================================
RCS file: /cvs/src/sys/compat/linux/linux_socket.h,v
retrieving revision 1.10
diff -u -p -r1.10 linux_socket.h
--- linux_socket.h      19 Jun 2012 11:28:20 -0000      1.10
+++ linux_socket.h      20 Jun 2012 11:23:44 -0000
@@ -122,6 +122,8 @@
 
 /* Mask out extra type-related options */
 #define LINUX_SOCKET_TYPE_MASK 0xf
+#define LINUX_SOCK_CLOEXEC     02000000
+#define LINUX_SOCK_NONBLOCK    00004000
 
 struct linux_sockaddr {
        unsigned short  sa_family;

Reply via email to