diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index a23501e2..adca13d3 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -375,8 +375,11 @@ class Arbiter(object): :attr graceful: boolean, If True (the default) workers will be killed gracefully (ie. trying to wait for the current connection) """ - - unlink = self.reexec_pid == self.master_pid == 0 and not self.systemd + unlink = ( + self.reexec_pid == self.master_pid == 0 + and not self.systemd + and not self.cfg.reuse_port + ) sock.close_sockets(self.LISTENERS, unlink) self.LISTENERS = [] diff --git a/tests/test_arbiter.py b/tests/test_arbiter.py index 5ab6e920..fa376ce7 100644 --- a/tests/test_arbiter.py +++ b/tests/test_arbiter.py @@ -12,6 +12,7 @@ except ImportError: import gunicorn.app.base import gunicorn.arbiter +from gunicorn.config import ReusePort class DummyApplication(gunicorn.app.base.BaseApplication): @@ -64,6 +65,15 @@ def test_arbiter_stop_does_not_unlink_systemd_listeners(close_sockets): close_sockets.assert_called_with([], False) +@mock.patch('gunicorn.sock.close_sockets') +def test_arbiter_stop_does_not_unlink_when_using_reuse_port(close_sockets): + arbiter = gunicorn.arbiter.Arbiter(DummyApplication()) + arbiter.cfg.settings['reuse_port'] = ReusePort() + arbiter.cfg.settings['reuse_port'].set(True) + arbiter.stop() + close_sockets.assert_called_with([], False) + + @mock.patch('os.getpid') @mock.patch('os.fork') @mock.patch('os.execvpe')