From 862491c4874e402840d6a8582a9027e3785291c3 Mon Sep 17 00:00:00 2001 From: Barret Rhoden Date: Thu, 31 Mar 2016 13:09:19 -0400 Subject: [PATCH 1/1] net: Fixup socket shims use of O_NONBLOCK (XCC) Chans are now nonblocking, not conversations. We find out about the desire for SOCK_NONBLOCK from socket()'s type argument. We save that in the Rock's sopts, and we check it whenever we open a chan *for that socket* (but not for new accepts). Rebuild glibc. Signed-off-by: Barret Rhoden --- .../glibc-2.19-akaros/sysdeps/akaros/accept.c | 27 +++++++++++++--------- .../sysdeps/akaros/plan9_sockets.c | 5 ++-- .../glibc-2.19-akaros/sysdeps/akaros/socket.c | 6 ++--- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/accept.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/accept.c index 55bd84d..a57f204 100644 --- a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/accept.c +++ b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/accept.c @@ -39,6 +39,7 @@ int accept(int fd, __SOCKADDR_ARG addr, socklen_t * __restrict alen) char *p; const char *net = 0; char listen[Ctlsize]; + int open_flags = O_RDWR; r = _sock_findrock(fd, 0); if (r == 0) { @@ -57,25 +58,29 @@ int accept(int fd, __SOCKADDR_ARG addr, socklen_t * __restrict alen) break; } /* at this point, our FD is for the data file. we need to open the - * listen file. The line is stored in r->ctl (e.g. /net/tcp/666/ctl) */ + * listen file. The line is stored in r->ctl (e.g. + * /net/tcp/666/ctl) */ strcpy(listen, r->ctl); p = strrchr(listen, '/'); if (p == 0) return -1; strcpy(p + 1, "listen"); - - lcfd = open(listen, O_RDWR); + open_flags |= (r->sopts & SOCK_NONBLOCK ? O_NONBLOCK : 0); + lcfd = open(listen, open_flags); if (lcfd < 0) return -1; - /* at this point, we have a new conversation, and lcfd is its ctl fd. - * nfd will be the FD for that conv's data file. sock_data will trade - * our lcfd for the data file fd. even if it fails, sock_data will - * close our lcfd for us. when it succeeds, it'll open the data file - * before closing lcfd, which will keep the converstation alive. + /* at this point, we have a new conversation, and lcfd is its ctl + * fd. nfd will be the FD for that conv's data file. sock_data + * will trade our lcfd for the data file fd. even if it fails, + * sock_data will close our lcfd for us. when it succeeds, it'll + * open the data file before closing lcfd, which will keep the + * converstation alive. * - * Note, we pass the listen socket's stype, but not it's sopts. If - * we implement something like accept4, that's where those sopts - * (e.g. O_CLOEXEC, O_NONBLOCK) will come from. */ + * Note, we pass the listen socket's stype, but not it's sopts. The + * sopts (e.g. SOCK_NONBLOCK) apply to the original socket, not to + * the new one. If we want to do something like accept4(), we'll + * want to pass the sopts for the *new* socket in stype. (Both the + * listen socket and the new socket have the same stype). */ nfd = _sock_data(lcfd, net, r->domain, r->stype, r->protocol, &nr); if (nfd < 0) return -1; diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.c index b35070b..64ff26a 100644 --- a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.c +++ b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.c @@ -199,13 +199,13 @@ void _sock_fd_closed(int fd) /* For a ctlfd and a few other settings, it opens and returns the corresponding * datafd. This will close cfd for you. */ - int _sock_data(int cfd, const char *net, int domain, int type, int protocol, Rock **rp) { int n, fd; Rock *r; char name[Ctlsize]; + int open_flags = O_RDWR; /* get the data file name */ n = read(cfd, name, sizeof(name) - 1); @@ -219,7 +219,8 @@ int _sock_data(int cfd, const char *net, int domain, int type, int protocol, snprintf(name, sizeof name, "/net/%s/%d/data", net, n); /* open data file */ - fd = open(name, O_RDWR); + open_flags |= (type & SOCK_NONBLOCK ? O_NONBLOCK : 0); + fd = open(name, open_flags); close(cfd); /* close this no matter what */ if (fd < 0) { errno = ENOBUFS; diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/socket.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/socket.c index 2d0ef88..d49c4ee 100644 --- a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/socket.c +++ b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/socket.c @@ -32,7 +32,6 @@ int __socket(int domain, int type, int protocol) { Rock *r; int cfd, n; - int open_flags = O_RDWR; int pfd[2]; const char *net; char msg[128]; @@ -42,12 +41,11 @@ int __socket(int domain, int type, int protocol) switch (domain) { case PF_INET: - open_flags |= (type & SOCK_NONBLOCK ? O_NONBLOCK : 0); /* get a free network directory */ switch (_sock_strip_opts(type)) { case SOCK_DGRAM: net = "udp"; - cfd = open("/net/udp/clone", open_flags); + cfd = open("/net/udp/clone", O_RDWR); /* All BSD UDP sockets are in 'headers' mode, where each * packet has the remote addr:port, local addr:port and * other info. */ @@ -66,7 +64,7 @@ int __socket(int domain, int type, int protocol) break; case SOCK_STREAM: net = "tcp"; - cfd = open("/net/tcp/clone", open_flags); + cfd = open("/net/tcp/clone", O_RDWR); break; default: errno = EPROTONOSUPPORT; -- 2.7.4