Skip to content

Commit c4064b4

Browse files
committed
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.
1 parent f8e71eb commit c4064b4

File tree

1 file changed

+27
-9
lines changed

1 file changed

+27
-9
lines changed

src/event/event_epoll.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ typedef struct dispatch_muxnote_s {
5151
int dmn_ident;
5252
uint32_t dmn_events;
5353
int16_t dmn_filter;
54-
bool dmn_socket_listener;
54+
bool dmn_skip_outq_ioctl;
55+
bool dmn_skip_inq_ioctl;
5556
} *dispatch_muxnote_t;
5657

5758
typedef struct dispatch_epoll_timeout_s {
@@ -143,7 +144,7 @@ _dispatch_muxnote_create(dispatch_unote_t du, uint32_t events)
143144
struct stat sb;
144145
int fd = du._du->du_ident;
145146
int16_t filter = du._du->du_filter;
146-
bool socket_listener = false;
147+
bool skip_outq_ioctl = false, skip_inq_ioctl = false;
147148
sigset_t sigmask;
148149

149150
switch (filter) {
@@ -173,11 +174,15 @@ _dispatch_muxnote_create(dispatch_unote_t du, uint32_t events)
173174
if (fd < 0) {
174175
return NULL;
175176
}
177+
// Linux doesn't support output queue size ioctls for regular files
178+
skip_outq_ioctl = true;
176179
} else if (S_ISSOCK(sb.st_mode)) {
177180
socklen_t vlen = sizeof(int);
178181
int v;
182+
// Linux doesn't support saying how many clients are ready to be
183+
// accept()ed for sockets
179184
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &v, &vlen) == 0) {
180-
socket_listener = (bool)v;
185+
skip_inq_ioctl = (bool)v;
181186
}
182187
}
183188
break;
@@ -193,7 +198,8 @@ _dispatch_muxnote_create(dispatch_unote_t du, uint32_t events)
193198
dmn->dmn_ident = du._du->du_ident;
194199
dmn->dmn_filter = filter;
195200
dmn->dmn_events = events;
196-
dmn->dmn_socket_listener = socket_listener;
201+
dmn->dmn_skip_outq_ioctl = skip_outq_ioctl;
202+
dmn->dmn_skip_inq_ioctl = skip_inq_ioctl;
197203
return dmn;
198204
}
199205

@@ -480,16 +486,28 @@ _dispatch_event_merge_signal(dispatch_muxnote_t dmn)
480486
static uintptr_t
481487
_dispatch_get_buffer_size(dispatch_muxnote_t dmn, bool writer)
482488
{
483-
unsigned long op = writer ? SIOCOUTQ : SIOCINQ;
484489
int n;
485490

486-
if (!writer && dmn->dmn_socket_listener) {
487-
// Linux doesn't support saying how many clients are ready to be
488-
// accept()ed
491+
if (writer ? dmn->dmn_skip_outq_ioctl : dmn->dmn_skip_inq_ioctl) {
489492
return 1;
490493
}
491494

492-
if (dispatch_assume_zero(ioctl(dmn->dmn_ident, op, &n))) {
495+
if (ioctl(dmn->dmn_ident, writer ? SIOCOUTQ : SIOCINQ, &n) != 0) {
496+
switch (errno) {
497+
case EINVAL:
498+
case ENOTTY:
499+
// this file descriptor actually doesn't support the buffer
500+
// size ioctl, remember that for next time to avoid the syscall.
501+
break;
502+
default:
503+
dispatch_assume_zero(errno);
504+
break;
505+
}
506+
if (writer) {
507+
dmn->dmn_skip_outq_ioctl = true;
508+
} else {
509+
dmn->dmn_skip_inq_ioctl = true;
510+
}
493511
return 1;
494512
}
495513
return (uintptr_t)n;

0 commit comments

Comments
 (0)