From 39987237eb36fd371a32c94370ad21caf32a9cfd Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 23 Jul 2019 15:54:35 +0200 Subject: [PATCH] Fix fpm timer event re-registration --- sapi/fpm/fpm/fpm_events.c | 26 +++++---- .../reload-uses-sigkill-as-last-measure.phpt | 56 +++++++++++++++++++ sapi/fpm/tests/tester.inc | 2 +- 3 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 sapi/fpm/tests/reload-uses-sigkill-as-last-measure.phpt diff --git a/sapi/fpm/fpm/fpm_events.c b/sapi/fpm/fpm/fpm_events.c index 81db9f8867a65..86592050c6ba5 100644 --- a/sapi/fpm/fpm/fpm_events.c +++ b/sapi/fpm/fpm/fpm_events.c @@ -433,17 +433,16 @@ void fpm_event_loop(int err) /* {{{ */ /* trigger timers */ q = fpm_event_queue_timer; while (q) { + struct fpm_event_queue_s *next = q->next; fpm_clock_get(&now); if (q->ev) { if (timercmp(&now, &q->ev->timeout, >) || timercmp(&now, &q->ev->timeout, ==)) { - fpm_event_fire(q->ev); - /* sanity check */ - if (fpm_globals.parent_pid != getpid()) { - return; - } - if (q->ev->flags & FPM_EV_PERSIST) { - fpm_event_set_timeout(q->ev, now); - } else { /* delete the event */ + struct fpm_event_s *ev = q->ev; + if (ev->flags & FPM_EV_PERSIST) { + fpm_event_set_timeout(ev, now); + } else { + /* Delete the event. Make sure this happens before it is fired, + * so that the event callback may register the same timer again. */ q2 = q; if (q->prev) { q->prev->next = q->next; @@ -457,13 +456,18 @@ void fpm_event_loop(int err) /* {{{ */ fpm_event_queue_timer->prev = NULL; } } - q = q->next; free(q2); - continue; + } + + fpm_event_fire(ev); + + /* sanity check */ + if (fpm_globals.parent_pid != getpid()) { + return; } } } - q = q->next; + q = next; } } } diff --git a/sapi/fpm/tests/reload-uses-sigkill-as-last-measure.phpt b/sapi/fpm/tests/reload-uses-sigkill-as-last-measure.phpt new file mode 100644 index 0000000000000..25c2cf25e2bcb --- /dev/null +++ b/sapi/fpm/tests/reload-uses-sigkill-as-last-measure.phpt @@ -0,0 +1,56 @@ +--TEST-- +If SIGQUIT and SIGTERM during reloading fail, SIGKILL should be sent +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester->request()->expectEmptyBody(); +$tester->signal('USR2'); +$tester->expectLogNotice('Reloading in progress ...'); +$tester->expectLogNotice('reloading: .*'); +$tester->expectLogNotice('using inherited socket fd=\d+, "127.0.0.1:\d+"'); +$tester->expectLogStartNotices(); +$tester->ping('{{ADDR}}'); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index 70c03ad70f1c5..bfa6fcd98cb46 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -627,7 +627,7 @@ class Tester $read = [$this->outDesc]; $write = null; $except = null; - if (stream_select($read, $write, $except, 2 )) { + if (stream_select($read, $write, $except, 3)) { return fgets($this->outDesc); } else { return null;