diff --git a/ChangeLog b/ChangeLog index 5bd26ea7..78b27b21 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,7 @@ Changes in 1.4.6-stable: o Fix a bug where setting the timeout on a bufferevent would take not effect if the event was already pending. o Fix a memory leak when using signals for some event bases; reported by Alexander Drozdov. o Add libevent.vcproj file to distribution to help with Windows build. + o Fix a problem with epoll() and reinit; problem report by Alexander Drozdov. Changes in 1.4.5-stable: o Fix connection keep-alive behavior for HTTP/1.0 @@ -89,7 +90,6 @@ Changes in 1.4.1-beta: o The configure script now takes an --enable-gcc-warnigns option that turns on many optional gcc warnings. (Nick has been building with these for a while, but they might be useful to other developers.) o When building with GCC, use the "format" attribute to verify type correctness of calls to printf-like functions. o removed linger from http server socket; reported by Ilya Martynov - o Rewrite win32.c backend to be O(n lg n) rather than O(n^2) o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr. o demote most http warnings to debug messages o Fix Solaris compilation; from Magne Mahre diff --git a/event.c b/event.c index 5b25959e..c70e5400 100644 --- a/event.c +++ b/event.c @@ -237,9 +237,20 @@ event_base_free(struct event_base *base) ++n_deleted; } + for (i = 0; i < base->nactivequeues; ++i) { + for (ev = TAILQ_FIRST(base->activequeues[i]); ev; ) { + struct event *next = TAILQ_NEXT(ev, ev_active_next); + if (!(ev->ev_flags & EVLIST_INTERNAL)) { + event_del(ev); + ++n_deleted; + } + ev = next; + } + } + if (n_deleted) event_debug(("%s: %d events were still set in base", - __func__, n_deleted)); + __func__, n_deleted)); if (base->evsel->dealloc != NULL) base->evsel->dealloc(base, base->evbase); @@ -272,6 +283,13 @@ event_reinit(struct event_base *base) if (!evsel->need_reinit) return (0); + /* prevent internal delete */ + if (base->sig.ev_signal_added) { + event_queue_remove(base, &base->sig.ev_signal, + EVLIST_INSERTED); + base->sig.ev_signal_added = 0; + } + if (base->evsel->dealloc != NULL) base->evsel->dealloc(base, base->evbase); evbase = base->evbase = evsel->init(base); diff --git a/signal.c b/signal.c index e36230ad..bcaa3f9b 100644 --- a/signal.c +++ b/signal.c @@ -334,7 +334,6 @@ evsignal_dealloc(struct event_base *base) for (i = 0; i < NSIG; ++i) { if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL) _evsignal_restore_handler(base, i); - assert(TAILQ_EMPTY(&base->sig.evsigevents[0])); } EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]); diff --git a/test/regress.c b/test/regress.c index ebd95140..e939d1d1 100644 --- a/test/regress.c +++ b/test/regress.c @@ -452,11 +452,25 @@ test_simpletimeout(void) #ifndef WIN32 extern struct event_base *current_base; + +static void +child_signal_cb(int fd, short event, void *arg) +{ + struct timeval tv; + int *pint = arg; + + *pint = 1; + + tv.tv_usec = 500000; + tv.tv_sec = 0; + event_loopexit(&tv); +} + static void test_fork(void) { - int status; - struct event ev; + int status, got_sigchld = 0; + struct event ev, sig_ev; pid_t pid; setup_test("After fork: "); @@ -467,6 +481,9 @@ test_fork(void) if (event_add(&ev, NULL) == -1) exit(1); + signal_set(&sig_ev, SIGCHLD, child_signal_cb, &got_sigchld); + signal_add(&sig_ev, NULL); + if ((pid = fork()) == 0) { /* in the child */ if (event_reinit(current_base) == -1) { @@ -474,6 +491,8 @@ test_fork(void) exit(1); } + signal_del(&sig_ev); + called = 0; event_dispatch(); @@ -505,6 +524,13 @@ test_fork(void) event_dispatch(); + if (!got_sigchld) { + fprintf(stdout, "FAILED (sigchld)\n"); + exit(1); + } + + signal_del(&sig_ev); + cleanup_test(); }