From ee6f5a651bf5061683558a524e1640fab2f0a02e Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Wed, 13 Jul 2011 22:43:57 +0200 Subject: [PATCH] Try to prevent recursive calls to stop --- mopidy/utils/network.py | 8 ++++++++ tests/utils/network_test.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/mopidy/utils/network.py b/mopidy/utils/network.py index 1d63f6e6..acb074d1 100644 --- a/mopidy/utils/network.py +++ b/mopidy/utils/network.py @@ -127,6 +127,8 @@ class Connection(object): self.send_lock = threading.Lock() self.send_buffer = '' + self.stopping = False + self.recv_id = None self.send_id = None self.timeout_id = None @@ -137,6 +139,12 @@ class Connection(object): self.enable_timeout() def stop(self, reason, level=logging.DEBUG): + if self.stopping: + logger.log(level, 'Already stopping: %s' % reason) + return + else: + self.stopping = True + logger.log(level, reason) try: diff --git a/tests/utils/network_test.py b/tests/utils/network_test.py index 9e41472f..52d8c51b 100644 --- a/tests/utils/network_test.py +++ b/tests/utils/network_test.py @@ -245,6 +245,7 @@ class ConnectionTest(unittest.TestCase): self.assertEqual(sentinel.port, self.mock.port) def test_stop_disables_recv_send_and_timeout(self): + self.mock.stopping = False self.mock.actor_ref = Mock() self.mock.sock = Mock(spec=socket.SocketType) @@ -254,6 +255,7 @@ class ConnectionTest(unittest.TestCase): self.mock.disable_timeout.assert_called_once_with() def test_stop_closes_socket(self): + self.mock.stopping = False self.mock.actor_ref = Mock() self.mock.sock = Mock(spec=socket.SocketType) @@ -261,6 +263,7 @@ class ConnectionTest(unittest.TestCase): self.mock.sock.close.assert_called_once_with() def test_stop_closes_socket_error(self): + self.mock.stopping = False self.mock.actor_ref = Mock() self.mock.sock = Mock(spec=socket.SocketType) self.mock.sock.close.side_effect = socket.error() @@ -269,6 +272,7 @@ class ConnectionTest(unittest.TestCase): self.mock.sock.close.assert_called_once_with() def test_stop_stops_actor(self): + self.mock.stopping = False self.mock.actor_ref = Mock() self.mock.sock = Mock(spec=socket.SocketType) @@ -276,14 +280,42 @@ class ConnectionTest(unittest.TestCase): self.mock.actor_ref.stop.assert_called_once_with() def test_stop_handles_actor_already_being_stopped(self): + self.mock.stopping = False self.mock.actor_ref = Mock() self.mock.actor_ref.stop.side_effect = pykka.ActorDeadError() self.mock.sock = Mock(spec=socket.SocketType) network.Connection.stop(self.mock, sentinel.reason) + def test_stop_sets_stopping_to_true(self): + self.mock.stopping = False + self.mock.actor_ref = Mock() + self.mock.sock = Mock(spec=socket.SocketType) + + network.Connection.stop(self.mock, sentinel.reason) + self.assertEqual(True, self.mock.stopping) + + def test_stop_does_not_proceed_when_already_stopping(self): + self.mock.stopping = True + self.mock.actor_ref = Mock() + self.mock.sock = Mock(spec=socket.SocketType) + + network.Connection.stop(self.mock, sentinel.reason) + self.assertEqual(0, self.mock.actor_ref.stop.call_count) + self.assertEqual(0, self.mock.sock.close.call_count) + + @patch.object(network.logger, 'log', new=Mock()) + def test_stop_logs_that_it_is_calling_itself(self): + self.mock.stopping = True + self.mock.actor_ref = Mock() + self.mock.sock = Mock(spec=socket.SocketType) + + network.Connection.stop(self.mock, sentinel.reason) + network.logger.log(any_int, any_unicode) + @patch.object(network.logger, 'log', new=Mock()) def test_stop_logs_reason(self): + self.mock.stopping = False self.mock.actor_ref = Mock() self.mock.sock = Mock(spec=socket.SocketType) @@ -293,6 +325,7 @@ class ConnectionTest(unittest.TestCase): @patch.object(network.logger, 'log', new=Mock()) def test_stop_logs_reason_with_level(self): + self.mock.stopping = False self.mock.actor_ref = Mock() self.mock.sock = Mock(spec=socket.SocketType)