Hi Willy,
Sending a patch proposal after like 40 hours of looking through what
happens and what event we might be missing, im now changing +-40 lines
of code.. And actually not 'really' changing the events requested.. But
rather kinda bringing the old 'previous state' comparison back..
Lemme know if its okay like this, you would like the new variable to be
renamed, the if/then/else restructured or just don't like it at all ;).
In the last case please do give a hint about what you would like instead :).
Regards,
PiBa-NL (Pieter)
From 21c191c036f740eb75a4fa59c23232b910cd695c Mon Sep 17 00:00:00 2001
From: PiBa-NL <piba.nl....@gmail.com>
Date: Sun, 15 Apr 2018 22:20:22 +0200
Subject: [PATCH] BUG/MEDIUM: kqueue/poll: only use EV_SET when actually
needing to add or remove event filters
Avoid event filters being added twice or deleted while not present causing
hanging requests.
Known reproduction:
With haproxy on a FreeBSD machine, and a IIS website with NTLM authentication
and using http-tunnel haproxy would fail to receive the request with the added
credentials to pass to the backend.
---
include/types/fd.h | 1 +
src/ev_kqueue.c | 36 +++++++++++++++++++++++++-----------
src/fd.c | 1 +
3 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/include/types/fd.h b/include/types/fd.h
index 0902e7f..243d7bb 100644
--- a/include/types/fd.h
+++ b/include/types/fd.h
@@ -115,6 +115,7 @@ struct fdtab {
__decl_hathreads(HA_SPINLOCK_T lock);
unsigned long thread_mask; /* mask of thread IDs authorized
to process the task */
unsigned long polled_mask; /* mask of thread IDs currently
polling this fd */
+ unsigned long polled_mask_write; /* mask of thread IDs currently
polling this fd */
unsigned long update_mask; /* mask of thread IDs having an
update for fd */
struct fdlist_entry cache; /* Entry in the fdcache */
void (*iocb)(int fd); /* I/O handler */
diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c
index a103ece..ecadec3 100644
--- a/src/ev_kqueue.c
+++ b/src/ev_kqueue.c
@@ -56,29 +56,43 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
en = fdtab[fd].state;
if (!(fdtab[fd].thread_mask & tid_bit) || !(en &
FD_EV_POLLED_RW)) {
- if (!(fdtab[fd].polled_mask & tid_bit)) {
+ if (!(fdtab[fd].polled_mask & tid_bit) &&
!(fdtab[fd].polled_mask_write & tid_bit)) {
/* fd was not watched, it's still not */
continue;
}
/* fd totally removed from poll list */
- EV_SET(&kev[changes++], fd, EVFILT_READ, EV_DELETE, 0,
0, NULL);
- EV_SET(&kev[changes++], fd, EVFILT_WRITE, EV_DELETE, 0,
0, NULL);
- HA_ATOMIC_AND(&fdtab[fd].polled_mask, ~tid_bit);
+ if (fdtab[fd].polled_mask & tid_bit) {
+ EV_SET(&kev[changes++], fd, EVFILT_READ,
EV_DELETE, 0, 0, NULL);
+ HA_ATOMIC_AND(&fdtab[fd].polled_mask, ~tid_bit);
+ }
+ if (fdtab[fd].polled_mask_write & tid_bit) {
+ EV_SET(&kev[changes++], fd, EVFILT_WRITE,
EV_DELETE, 0, 0, NULL);
+ HA_ATOMIC_AND(&fdtab[fd].polled_mask_write,
~tid_bit);
+ }
}
else {
/* OK fd has to be monitored, it was either added or
changed */
- if (en & FD_EV_POLLED_R)
- EV_SET(&kev[changes++], fd, EVFILT_READ,
EV_ADD, 0, 0, NULL);
- else if (fdtab[fd].polled_mask & tid_bit)
+ if (en & FD_EV_POLLED_R) {
+ if (!(fdtab[fd].polled_mask & tid_bit)) {
+ EV_SET(&kev[changes++], fd,
EVFILT_READ, EV_ADD, 0, 0, NULL);
+ HA_ATOMIC_OR(&fdtab[fd].polled_mask,
tid_bit);
+ }
+ } else if (fdtab[fd].polled_mask & tid_bit) {
EV_SET(&kev[changes++], fd, EVFILT_READ,
EV_DELETE, 0, 0, NULL);
+ HA_ATOMIC_AND(&fdtab[fd].polled_mask, ~tid_bit);
+ }
- if (en & FD_EV_POLLED_W)
- EV_SET(&kev[changes++], fd, EVFILT_WRITE,
EV_ADD, 0, 0, NULL);
- else if (fdtab[fd].polled_mask & tid_bit)
+ if (en & FD_EV_POLLED_W) {
+ if (!(fdtab[fd].polled_mask_write & tid_bit)) {
+ EV_SET(&kev[changes++], fd,
EVFILT_WRITE, EV_ADD, 0, 0, NULL);
+
HA_ATOMIC_OR(&fdtab[fd].polled_mask_write, tid_bit);
+ }
+ } else if (fdtab[fd].polled_mask_write & tid_bit) {
EV_SET(&kev[changes++], fd, EVFILT_WRITE,
EV_DELETE, 0, 0, NULL);
+ HA_ATOMIC_AND(&fdtab[fd].polled_mask_write,
~tid_bit);
+ }
- HA_ATOMIC_OR(&fdtab[fd].polled_mask, tid_bit);
}
}
if (changes)
diff --git a/src/fd.c b/src/fd.c
index 1af64e5..57aeb5c 100644
--- a/src/fd.c
+++ b/src/fd.c
@@ -369,6 +369,7 @@ static void fd_dodelete(int fd, int do_close)
fdtab[fd].thread_mask = 0;
if (do_close) {
fdtab[fd].polled_mask = 0;
+ fdtab[fd].polled_mask_write = 0;
close(fd);
}
HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
--
2.10.1.windows.1