Track listen FDs in socket rocks [1/3] (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 6 Jan 2016 15:14:52 +0000 (10:14 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 14 Jan 2016 21:04:46 +0000 (16:04 -0500)
Instead of only opening the listen file on demand and having our user
close it (which is a huge mess), we just open it right away and close it
when the socket / Rock is closed.

This will help out epoll, which currently will deadlock if it attempts
to close a listen_fd while holding its own locks, since epoll itself has
a close callback.

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/listen.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.h

index f3837ac..49b2dde 100644 (file)
@@ -67,6 +67,8 @@ int __listen(int fd, int backlog)
                        }
                        close(cfd);
                        r->is_listener = TRUE;
+                       if (_rock_open_listen_fd(r) < 0)
+                               return -1;
                        return 0;
                case PF_UNIX:
                        if (r->other < 0) {
index 924551c..3729c6d 100644 (file)
@@ -189,6 +189,12 @@ Rock *_sock_newrock(int fd)
 
 void _sock_fd_closed(int fd)
 {
+       Rock *r = _sock_findrock(fd, 0);
+
+       if (!r)
+               return;
+       if (r->is_listener)
+               close(r->listen_fd);
 }
 
 /* For a ctlfd and a few other settings, it opens and returns the corresponding
@@ -287,22 +293,23 @@ int _sock_get_opts(int type)
        return type & (SOCK_NONBLOCK | SOCK_CLOEXEC);
 }
 
-/* Used by user/iplib (e.g. epoll).  Opens and returns the FD for the
- * conversation's listen fd, which the caller needs to close.  Returns -1 if the
- * FD is not a listener. */
+/* Temp dummy, for compilation */
 int _sock_get_listen_fd(int sock_fd)
 {
+       return -1;
+}
+
+/* Opens the FD for "listen", and attaches it to the Rock.  When the dfd (and
+ * thus the Rock) closes, we'll close the listen file too.  Returns the FD on
+ * success, -1 on error. */
+int _rock_open_listen_fd(Rock *r)
+{
        char listen_file[Ctlsize + 3];
        char *x, *last_ctl;
-       Rock *r = _sock_findrock(sock_fd, 0);
        int ret;
 
-       if (!r)
-               return -1;
        if (!r->is_listener)
                return -1;
-       /* We want an FD for the "listen" file.  This is for epoll.  We
-        * could optimize and only do this on demand, but whatever. */
        strncpy(listen_file, r->ctl, sizeof(listen_file));
        /* We want the conversation directory.  We can find the last "ctl"
         * in the CTL name (they could have mounted at /ctlfoo/net/) */
@@ -324,9 +331,8 @@ int _sock_get_listen_fd(int sock_fd)
        return ret;
 }
 
-/* Used by user/iplib (e.g. epoll).  Looks up a previously opened FD for the
- * listen file for this conversation.  Returns -1 if the FD is not a listener
- * with an already-opened listen FD. */
+/* Used by user/iplib (e.g. epoll).  Looks up the FD listen file for this
+ * conversation.  Returns -1 if the FD is not a listener. */
 int _sock_lookup_listen_fd(int sock_fd)
 {
        Rock *r = _sock_findrock(sock_fd, 0);
index d0a6206..2536224 100644 (file)
@@ -72,6 +72,8 @@ extern void _sock_ingetaddr(Rock *, struct sockaddr_in *, socklen_t *,
                                                        const char *);
 extern int _sock_strip_opts(int type);
 extern int _sock_get_opts(int type);
+extern int _rock_open_listen_fd(Rock *r);
+extern int _sock_lookup_listen_fd(int sock_fd);
 
 extern void _syserrno(void);