PYTHON-525 Try to halt monitors before exiting.

This commit is contained in:
A. Jesse Jiryu Davis 2014-09-24 19:11:57 -04:00
parent cfcc601922
commit fea501f314
2 changed files with 49 additions and 1 deletions

View File

@ -67,6 +67,7 @@ class Monitor(object):
thread = threading.Thread(target=self.run)
thread.daemon = True
self._thread = weakref.proxy(thread)
register_monitor(self)
thread.start()
def close(self):
@ -171,6 +172,11 @@ class Monitor(object):
return IsMaster(result['data'][0]), time.time() - start
# MONITORS has a weakref to each running Monitor. A Monitor is kept alive by
# a strong reference from its Server and its Thread. Once both are destroyed
# the Monitor is garbage-collected and removed from MONITORS. If, however,
# any threads are still running when the interpreter begins to shut down,
# we attempt to halt and join them to avoid spurious errors.
MONITORS = set()
@ -192,6 +198,6 @@ def shutdown_monitors():
monitor = ref()
if monitor:
monitor.close()
monitor.join()
monitor.join(10)
atexit.register(shutdown_monitors)

42
test/test_monitor.py Normal file
View File

@ -0,0 +1,42 @@
# Copyright 2014 MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test the monitor module."""
import gc
import sys
sys.path[0:0] = [""]
from pymongo.monitor import MONITORS
from test import unittest, port, host, IntegrationTest
from test.utils import get_client, wait_until
class TestMonitor(IntegrationTest):
def test_atexit_hook(self):
n_monitors = len(MONITORS)
client = get_client(host, port)
wait_until(lambda: len(MONITORS) == n_monitors + 1,
'register new monitor')
del client
gc.collect()
wait_until(lambda: len(MONITORS) == n_monitors,
'unregister monitor')
if __name__ == "__main__":
unittest.main()