the buffer size ioctls on linux return EINVAL when it's not supported
Make sure we don't keep doing these syscalls and log stupid errors about
it failing forever.
Signed-off-by: Daniel A. Steffen <dsteffen@apple.com>
diff --git a/src/event/event_epoll.c b/src/event/event_epoll.c
index 419cb07..c003bac 100644
--- a/src/event/event_epoll.c
+++ b/src/event/event_epoll.c
@@ -51,7 +51,8 @@
int dmn_ident;
uint32_t dmn_events;
int16_t dmn_filter;
- bool dmn_socket_listener;
+ bool dmn_skip_outq_ioctl;
+ bool dmn_skip_inq_ioctl;
} *dispatch_muxnote_t;
typedef struct dispatch_epoll_timeout_s {
@@ -143,7 +144,7 @@
struct stat sb;
int fd = du._du->du_ident;
int16_t filter = du._du->du_filter;
- bool socket_listener = false;
+ bool skip_outq_ioctl = false, skip_inq_ioctl = false;
sigset_t sigmask;
switch (filter) {
@@ -173,11 +174,15 @@
if (fd < 0) {
return NULL;
}
+ // Linux doesn't support output queue size ioctls for regular files
+ skip_outq_ioctl = true;
} else if (S_ISSOCK(sb.st_mode)) {
socklen_t vlen = sizeof(int);
int v;
+ // Linux doesn't support saying how many clients are ready to be
+ // accept()ed for sockets
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &v, &vlen) == 0) {
- socket_listener = (bool)v;
+ skip_inq_ioctl = (bool)v;
}
}
break;
@@ -193,7 +198,8 @@
dmn->dmn_ident = du._du->du_ident;
dmn->dmn_filter = filter;
dmn->dmn_events = events;
- dmn->dmn_socket_listener = socket_listener;
+ dmn->dmn_skip_outq_ioctl = skip_outq_ioctl;
+ dmn->dmn_skip_inq_ioctl = skip_inq_ioctl;
return dmn;
}
@@ -480,16 +486,28 @@
static uintptr_t
_dispatch_get_buffer_size(dispatch_muxnote_t dmn, bool writer)
{
- unsigned long op = writer ? SIOCOUTQ : SIOCINQ;
int n;
- if (!writer && dmn->dmn_socket_listener) {
- // Linux doesn't support saying how many clients are ready to be
- // accept()ed
+ if (writer ? dmn->dmn_skip_outq_ioctl : dmn->dmn_skip_inq_ioctl) {
return 1;
}
- if (dispatch_assume_zero(ioctl(dmn->dmn_ident, op, &n))) {
+ if (ioctl(dmn->dmn_ident, writer ? SIOCOUTQ : SIOCINQ, &n) != 0) {
+ switch (errno) {
+ case EINVAL:
+ case ENOTTY:
+ // this file descriptor actually doesn't support the buffer
+ // size ioctl, remember that for next time to avoid the syscall.
+ break;
+ default:
+ dispatch_assume_zero(errno);
+ break;
+ }
+ if (writer) {
+ dmn->dmn_skip_outq_ioctl = true;
+ } else {
+ dmn->dmn_skip_inq_ioctl = true;
+ }
return 1;
}
return (uintptr_t)n;