about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@yhbt.net>2010-12-25 23:00:05 +0000
committerEric Wong <e@yhbt.net>2010-12-25 23:00:05 +0000
commit5280f35f131d88f90afffff0e10f7900530728aa (patch)
tree556bf9a4e2a81986a5764eb76dbfac98168eb0db
parentb859c4a12905cbd71d19cde2aaa9f88ec0374cc5 (diff)
downloadkgio-5280f35f131d88f90afffff0e10f7900530728aa.tar.gz
kgio may occasionally be built on a system with accept4()
and then deployed on one without it.   Handle this case
gracefully since it unfortunately happens on production systems.
-rw-r--r--ext/kgio/accept.c9
-rw-r--r--ext/kgio/missing/accept4.h11
2 files changed, 17 insertions, 3 deletions
diff --git a/ext/kgio/accept.c b/ext/kgio/accept.c
index 4762676..4856234 100644
--- a/ext/kgio/accept.c
+++ b/ext/kgio/accept.c
@@ -56,8 +56,15 @@ static VALUE get_accepted(VALUE klass)
 static VALUE xaccept(void *ptr)
 {
         struct accept_args *a = ptr;
+        int rv;
+
+        rv = accept_fn(a->fd, a->addr, a->addrlen, accept4_flags);
+        if (rv == -1 && errno == ENOSYS && accept_fn != my_accept4) {
+                accept_fn = my_accept4;
+                rv = accept_fn(a->fd, a->addr, a->addrlen, accept4_flags);
+        }
 
-        return (VALUE)accept4(a->fd, a->addr, a->addrlen, accept4_flags);
+        return (VALUE)rv;
 }
 
 #ifdef HAVE_RB_THREAD_BLOCKING_REGION
diff --git a/ext/kgio/missing/accept4.h b/ext/kgio/missing/accept4.h
index f2f3ba9..22bd9bc 100644
--- a/ext/kgio/missing/accept4.h
+++ b/ext/kgio/missing/accept4.h
@@ -13,10 +13,11 @@
 #      define SOCK_NONBLOCK O_NONBLOCK
 #    endif
 #  endif
+#endif /* !HAVE_ACCEPT4 */
 
 /* accept4() is currently a Linux-only goodie */
 static int
-accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
+my_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
 {
         int fd = accept(sockfd, addr, addrlen);
 
@@ -49,4 +50,10 @@ accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
         }
         return fd;
 }
-#endif /* !HAVE_ACCEPT4 */
+
+typedef int accept_fn_t(int, struct sockaddr *, socklen_t *, int);
+#ifdef HAVE_ACCEPT4
+static accept_fn_t *accept_fn = accept4;
+#else
+static accept_fn_t *accept_fn = my_accept4;
+#endif