On Tue, Jun 19, 2012 at 02:02:03PM -0700, Philip Guenther wrote:
> On Tue, Jun 19, 2012 at 1:26 AM, Paul Irofti <[email protected]> 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;