From: Arran Cudbard-Bell Date: Mon, 9 Apr 2018 13:24:39 +0000 (+0600) Subject: Leave events in the rbtree if they were not removed from kevent X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a8ef63ff3291d4bfa1b31926d02cf55b92d32792;p=thirdparty%2Ffreeradius-server.git Leave events in the rbtree if they were not removed from kevent Distinguish between deferred frees and kevent errors in fr_event_fd_delete. --- diff --git a/src/lib/util/event.c b/src/lib/util/event.c index 0f4eaa71854..4442641363c 100644 --- a/src/lib/util/event.c +++ b/src/lib/util/event.c @@ -618,12 +618,16 @@ static int _event_fd_delete(fr_event_fd_t *ef) */ count = fr_event_build_evset(evset, sizeof(evset)/sizeof(*evset), &ef->active, ef, &funcs, &ef->active); if (count > 0) { + int ret; + /* - * If this fails, assert on debug builds, but ignore it at run-time. + * If this fails, assert on debug builds. */ - if (kevent(el->kq, evset, count, NULL, 0, NULL) < 0) { - (void) fr_cond_assert_msg(false, "FD was closed without being removed from the KQ: %s", - fr_syserror(errno)); + ret = kevent(el->kq, evset, count, NULL, 0, NULL); + if (!fr_cond_assert_msg(ret >= 0, + "FD was closed without being removed from the KQ: %s", + fr_syserror(errno)) { + return -1; /* Prevent the free, and leave the fd in the trees */ } } @@ -693,10 +697,18 @@ int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter) } /* - * Destructor may prevent ef from being - * freed if kevent de-registration fails. + * Free will normally fail if it's + * a deferred free. There is a special + * case for kevent failures though. + * + * We distinguish between the two by + * looking to see if the ef is still + * in the even tree. + * + * Talloc returning -1 guarantees the + * memory has not been freed. */ - if (unlikely(talloc_free(ef) < 0)) return -1; + if ((talloc_free(ef) == -1) && ef->is_registered) return -1; return 0; }