From 1c3c8eefd0a40d4938d6f05969c886988116a425 Mon Sep 17 00:00:00 2001 From: Quentin Armitage Date: Wed, 6 Nov 2019 23:15:23 +0000 Subject: [PATCH] Resolve file descriptor errors on reload If a read or write thread was on the thread reaady queue when a reload was processed, the file descriptor was not removed from the epoll instance. This commit ensures that file descriptors relating to threads on the thread ready queue are removed from the epoll instance during a reload. Signed-off-by: Quentin Armitage --- keepalived/bfd/bfd_scheduler.c | 2 +- keepalived/check/check_bfd.c | 2 +- keepalived/vrrp/vrrp_scheduler.c | 2 +- lib/scheduler.c | 31 +++++++++++++++++++------------ lib/scheduler.h | 3 ++- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/keepalived/bfd/bfd_scheduler.c b/keepalived/bfd/bfd_scheduler.c index 5c3d0691..d51d420f 100644 --- a/keepalived/bfd/bfd_scheduler.c +++ b/keepalived/bfd/bfd_scheduler.c @@ -908,7 +908,7 @@ bfd_receiver_thread(thread_ref_t thread) data->thread_in = NULL; /* Ignore THREAD_READ_TIMEOUT */ - if (thread->type == THREAD_READY_FD) { + if (thread->type == THREAD_READY_READ_FD) { if (!bfd_receive_packet(&pkt, fd, bfd_buffer, BFD_BUFFER_SIZE)) bfd_handle_packet(&pkt); } diff --git a/keepalived/check/check_bfd.c b/keepalived/check/check_bfd.c index 4bd8af23..f9590c30 100644 --- a/keepalived/check/check_bfd.c +++ b/keepalived/check/check_bfd.c @@ -290,7 +290,7 @@ bfd_check_thread(thread_ref_t thread) bfd_thread = thread_add_read(master, bfd_check_thread, NULL, thread->u.f.fd, TIMER_NEVER, false); - if (thread->type != THREAD_READY_FD) + if (thread->type != THREAD_READY_READ_FD) return 0; while (read(thread->u.f.fd, &evt, sizeof(bfd_event_t)) != -1) diff --git a/keepalived/vrrp/vrrp_scheduler.c b/keepalived/vrrp/vrrp_scheduler.c index 91a4898c..7e6da60a 100644 --- a/keepalived/vrrp/vrrp_scheduler.c +++ b/keepalived/vrrp/vrrp_scheduler.c @@ -762,7 +762,7 @@ vrrp_bfd_thread(thread_ref_t thread) bfd_thread = thread_add_read(master, vrrp_bfd_thread, NULL, thread->u.f.fd, TIMER_NEVER, false); - if (thread->type != THREAD_READY_FD) + if (thread->type != THREAD_READY_READ_FD) return 0; while (read(thread->u.f.fd, &evt, sizeof(bfd_event_t)) != -1) diff --git a/lib/scheduler.c b/lib/scheduler.c index 8fc2a032..3cd7b65a 100644 --- a/lib/scheduler.c +++ b/lib/scheduler.c @@ -116,7 +116,8 @@ get_thread_type_str(thread_type_t id) if (id == THREAD_CHILD_TERMINATED) return "CHILD_TERMINATED"; if (id == THREAD_TERMINATE_START) return "TERMINATE_START"; if (id == THREAD_TERMINATE) return "TERMINATE"; - if (id == THREAD_READY_FD) return "READY_FD"; + if (id == THREAD_READY_READ_FD) return "READY_READ_FD"; + if (id == THREAD_READY_WRITE_FD) return "READY_WRITE_FD"; if (id == THREAD_READ_ERROR) return "READ_ERROR"; if (id == THREAD_WRITE_ERROR) return "WRITE_ERROR"; #ifdef USE_SIGNAL_THREADS @@ -859,7 +860,8 @@ thread_destroy_rb(thread_master_t *m, rb_root_cached_t *root) if (thread->type == THREAD_READ || thread->type == THREAD_WRITE || - thread->type == THREAD_READY_FD || + thread->type == THREAD_READY_READ_FD || + thread->type == THREAD_READY_WRITE_FD || thread->type == THREAD_READ_TIMEOUT || thread->type == THREAD_WRITE_TIMEOUT || thread->type == THREAD_READ_ERROR || @@ -1409,14 +1411,18 @@ thread_cancel(thread_ref_t thread_cp) rb_erase_cached(&thread->n, &m->child); rb_erase(&thread->rb_data, &m->child_pid); break; - case THREAD_READY_FD: + case THREAD_READY_READ_FD: case THREAD_READ_TIMEOUT: + if (thread->event) + thread_event_del(thread, THREAD_FL_EPOLL_READ_BIT); + list_head_del(&thread->next); + break; + case THREAD_READY_WRITE_FD: case THREAD_WRITE_TIMEOUT: - if (thread->event) { - rb_erase(&thread->event->n, &m->io_events); - FREE(thread->event); - } - /* ... falls through ... */ + if (thread->event) + thread_event_del(thread, THREAD_FL_EPOLL_WRITE_BIT); + list_head_del(&thread->next); + break; case THREAD_EVENT: case THREAD_READY: #ifdef USE_SIGNAL_THREADS @@ -1735,7 +1741,7 @@ thread_fetch_next_queue(thread_master_t *m) , ev->fd, ep_ev->events); continue; } - thread_move_ready(m, &m->read, ev->read, THREAD_READY_FD); + thread_move_ready(m, &m->read, ev->read, THREAD_READY_READ_FD); ev->read = NULL; } @@ -1746,7 +1752,7 @@ thread_fetch_next_queue(thread_master_t *m) , ev->fd, ep_ev->events); continue; } - thread_move_ready(m, &m->write, ev->write, THREAD_READY_FD); + thread_move_ready(m, &m->write, ev->write, THREAD_READY_WRITE_FD); ev->write = NULL; } } @@ -1804,7 +1810,8 @@ process_threads(thread_master_t *m) * snmp_read, bfd_receiver, bfd pipe in vrrp/check, dbus pipe or netlink fds. */ thread = thread_trim_head(thread_list); if (!shutting_down || - (thread->type == THREAD_READY_FD && + ((thread->type == THREAD_READY_READ_FD || + thread->type == THREAD_READY_WRITE_FD) && (thread->u.f.fd == m->timer_fd || thread->u.f.fd == m->signal_fd #ifdef _WITH_SNMP_ @@ -1823,7 +1830,7 @@ process_threads(thread_master_t *m) shutting_down = true; } - m->current_event = (thread->type == THREAD_READY_FD) ? thread->event : NULL; + m->current_event = (thread->type == THREAD_READY_READ_FD || thread->type == THREAD_READY_WRITE_FD) ? thread->event : NULL; thread_type = thread->type; thread_add_unuse(master, thread); diff --git a/lib/scheduler.h b/lib/scheduler.h index 69324fe0..fea99cd0 100644 --- a/lib/scheduler.h +++ b/lib/scheduler.h @@ -56,7 +56,8 @@ typedef enum { THREAD_CHILD_TERMINATED, THREAD_TERMINATE_START, THREAD_TERMINATE, - THREAD_READY_FD, + THREAD_READY_READ_FD, + THREAD_READY_WRITE_FD, THREAD_READ_ERROR, THREAD_WRITE_ERROR, #ifdef USE_SIGNAL_THREADS -- 2.23.0