PYTHON-1205 - Use SIGALRM instead of interrupt_main on non-Windows

This commit is contained in:
Bernie Hackett 2017-02-06 13:36:23 -08:00
parent 544fd06f6f
commit 80fdf61cdb
2 changed files with 71 additions and 34 deletions

View File

@ -16,11 +16,12 @@
import datetime
import os
import threading
import signal
import socket
import sys
import time
import thread
import threading
import time
import unittest
import warnings
@ -935,31 +936,53 @@ with client.start_request() as request:
db.drop_collection('foo')
db.foo.insert({'_id': 1})
def interrupter():
# Raises KeyboardInterrupt in the main thread
time.sleep(0.25)
thread.interrupt_main()
thread.start_new_thread(interrupter, ())
raised = False
old_signal_handler = None
try:
# Will be interrupted by a KeyboardInterrupt.
db.foo.find({'$where': where}).next()
except KeyboardInterrupt:
raised = True
# Platform-specific hacks for raising a KeyboardInterrupt on the
# main thread while find() is in-progress: On Windows, SIGALRM is
# unavailable so we use a second thread. In our Evergreen setup on
# Linux, the thread technique causes an error in the test at
# sock.recv(): TypeError: 'int' object is not callable
# We don't know what causes this, so we hack around it.
# Can't use self.assertRaises() because it doesn't catch system
# exceptions
self.assertTrue(raised, "Didn't raise expected KeyboardInterrupt")
if sys.platform == 'win32':
def interrupter():
# Raises KeyboardInterrupt in the main thread
time.sleep(0.25)
thread.interrupt_main()
thread.start_new_thread(interrupter, ())
else:
# Convert SIGALRM to SIGINT -- it's hard to schedule a SIGINT
# for one second in the future, but easy to schedule SIGALRM.
def sigalarm(num, frame):
raise KeyboardInterrupt
old_signal_handler = signal.signal(signal.SIGALRM, sigalarm)
signal.alarm(1)
raised = False
try:
# Will be interrupted by a KeyboardInterrupt.
db.foo.find({'$where': where}).next()
except KeyboardInterrupt:
raised = True
# Can't use self.assertRaises() because it doesn't catch system
# exceptions
self.assertTrue(raised, "Didn't raise expected KeyboardInterrupt")
# Raises AssertionError due to PYTHON-294 -- Mongo's response to
# the previous find() is still waiting to be read on the socket,
# so the request id's don't match.
self.assertEqual(
{'_id': 1},
db.foo.find().next()
)
finally:
if old_signal_handler:
signal.signal(signal.SIGALRM, old_signal_handler)
# Raises AssertionError due to PYTHON-294 -- Mongo's response to the
# previous find() is still waiting to be read on the socket, so the
# request id's don't match.
self.assertEqual(
{'_id': 1},
db.foo.find().next()
)
def test_operation_failure_without_request(self):
# Ensure MongoClient doesn't close socket after it gets an error

View File

@ -956,15 +956,29 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin):
db.foo.insert({'_id': 1})
old_signal_handler = None
try:
def interrupter():
time.sleep(0.25)
# Platform-specific hacks for raising a KeyboardInterrupt on the
# main thread while find() is in-progress: On Windows, SIGALRM is
# unavailable so we use a second thread. In our Evergreen setup on
# Linux, the thread technique causes an error in the test at
# sock.recv(): TypeError: 'int' object is not callable
# We don't know what causes this, so we hack around it.
# Raises KeyboardInterrupt in the main thread
thread.interrupt_main()
if sys.platform == 'win32':
def interrupter():
# Raises KeyboardInterrupt in the main thread
time.sleep(0.25)
thread.interrupt_main()
thread.start_new_thread(interrupter, ())
thread.start_new_thread(interrupter, ())
else:
# Convert SIGALRM to SIGINT -- it's hard to schedule a SIGINT
# for one second in the future, but easy to schedule SIGALRM.
def sigalarm(num, frame):
raise KeyboardInterrupt
old_signal_handler = signal.signal(signal.SIGALRM, sigalarm)
signal.alarm(1)
raised = False
try:
@ -975,11 +989,11 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin):
# Can't use self.assertRaises() because it doesn't catch system
# exceptions
self.assertTrue(raised, "Didn't raise expected ConnectionFailure")
self.assertTrue(raised, "Didn't raise expected KeyboardInterrupt")
# Raises AssertionError due to PYTHON-294 -- Mongo's response to the
# previous find() is still waiting to be read on the socket, so the
# request id's don't match.
# Raises AssertionError due to PYTHON-294 -- Mongo's response to
# the previous find() is still waiting to be read on the socket,
# so the request id's don't match.
self.assertEqual(
{'_id': 1},
db.foo.find().next()