about summary refs log tree commit homepage
path: root/socket_alive.c
diff options
context:
space:
mode:
Diffstat (limited to 'socket_alive.c')
-rw-r--r--socket_alive.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/socket_alive.c b/socket_alive.c
new file mode 100644
index 0000000..37e52a1
--- /dev/null
+++ b/socket_alive.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012-2013, Eric Wong <normalperson@yhbt.net>
+ * License: GPLv3 or later (see COPYING for details)
+ */
+#include "cmogstored.h"
+
+/*
+ * check for POLLERR/POLLHUP on the socket to see if it died while
+ * we were in the queue.  This can save us from expensive processing.
+ */
+bool mog_socket_alive(struct mog_fd *mfd)
+{
+        static const short dead_events = POLLERR | POLLHUP;
+        struct pollfd fds = { .fd = mfd->fd, .events = POLLIN };
+        int rc;
+        int nbytes;
+
+        do {
+                rc = poll(&fds, 1, 0);
+        } while (rc < 0 && errno == EINTR);
+
+        if (rc == 1) {
+                if (fds.revents & POLLIN) {
+                        CHECK(int, 0, ioctl(mfd->fd, FIONREAD, &nbytes));
+                        return (nbytes <= 0) ? false : true;
+                }
+                return (fds.revents & dead_events) ? false : true;
+        }
+        if (rc == 0)
+                return true;
+
+        assert(rc < 0 && "poll returned unexpected value");
+
+        if (errno == ENOMEM || errno == EAGAIN)
+                return false; /* kernel is in trouble, abort */
+
+        assert(0 && "poll usage bug?");
+        return false;
+}