def test_3611(self): import gc # A re-raised exception in a __del__ caused the __context__ # to be cleared class C: def __del__(self): try: 1 / 0 except: raise def f(): x = C() try: try: f.x except AttributeError: # make x.__del__ trigger del x gc.collect() # For PyPy or other GCs. raise TypeError except Exception as e: self.assertNotEqual(e.__context__, None) self.assertIsInstance(e.__context__, AttributeError) with support.catch_unraisable_exception() as cm: f() self.assertEqual(ZeroDivisionError, cm.unraisable.exc_type)
def test_3611(self): # A re-raised exception in a __del__ caused the __context__ # to be cleared class C: def __del__(self): try: 1/0 except: raise def f(): x = C() try: try: x.x except AttributeError: del x raise TypeError except Exception as e: self.assertNotEqual(e.__context__, None) self.assertIsInstance(e.__context__, AttributeError) with support.catch_unraisable_exception() as cm: f() self.assertEqual(ZeroDivisionError, cm.unraisable.exc_type)
def test_broken_getattr_handling(self): """ Test subiterator with a broken getattr implementation """ class Broken: def __iter__(self): return self def __next__(self): return 1 def __getattr__(self, attr): 1 / 0 def g(): yield from Broken() with self.assertRaises(ZeroDivisionError): gi = g() self.assertEqual(next(gi), 1) gi.send(1) with self.assertRaises(ZeroDivisionError): gi = g() self.assertEqual(next(gi), 1) gi.throw(AttributeError) with support.catch_unraisable_exception() as cm: gi = g() self.assertEqual(next(gi), 1) gi.close() self.assertEqual(ZeroDivisionError, cm.unraisable.exc_type)
def wrapper(self, *args, **kwargs): with catch_unraisable_exception() as cm: # First, run the test with traceback enabled. with check_tracebacks(self, cm, exc, _regex, name): func(self, *args, **kwargs) # Then run the test with traceback disabled. func(self, *args, **kwargs)
def assert_raises_unraisable(self, exc_type, func, *args): with support.catch_unraisable_exception() as cm: atexit.register(func, *args) atexit._run_exitfuncs() self.assertEqual(cm.unraisable.object, func) self.assertEqual(cm.unraisable.exc_type, exc_type) self.assertEqual(type(cm.unraisable.exc_value), exc_type)
def test_stress_modifying_handlers(self): # bpo-43406: race condition between trip_signal() and signal.signal signum = signal.SIGUSR1 num_sent_signals = 0 num_received_signals = 0 do_stop = False def custom_handler(signum, frame): nonlocal num_received_signals num_received_signals += 1 def set_interrupts(): nonlocal num_sent_signals while not do_stop: signal.raise_signal(signum) num_sent_signals += 1 def cycle_handlers(): while num_sent_signals < 100: for i in range(20000): # Cycle between a Python-defined and a non-Python handler for handler in [custom_handler, signal.SIG_IGN]: signal.signal(signum, handler) old_handler = signal.signal(signum, custom_handler) self.addCleanup(signal.signal, signum, old_handler) t = threading.Thread(target=set_interrupts) try: ignored = False with support.catch_unraisable_exception() as cm: t.start() cycle_handlers() do_stop = True t.join() if cm.unraisable is not None: # An unraisable exception may be printed out when # a signal is ignored due to the aforementioned # race condition, check it. self.assertIsInstance(cm.unraisable.exc_value, OSError) self.assertIn( f"Signal {signum} ignored due to race condition", str(cm.unraisable.exc_value)) ignored = True # bpo-43406: Even if it is unlikely, it's technically possible that # all signals were ignored because of race conditions. if not ignored: # Sanity check that some signals were received, but not all self.assertGreater(num_received_signals, 0) self.assertLess(num_received_signals, num_sent_signals) finally: do_stop = True t.join()
def expect_unraisable(self, exc_type, exc_msg=None): with support.catch_unraisable_exception() as cm: yield self.assertIsInstance(cm.unraisable.exc_value, exc_type) if exc_msg is not None: self.assertEqual(str(cm.unraisable.exc_value), exc_msg) self.assertEqual( cm.unraisable.err_msg, "Exception ignored on calling ctypes " "callback function") self.assertIs(cm.unraisable.object, callback_func)
def test_bad_counter_during_dealloc(self): # bpo-3895 import _lsprof with support.catch_unraisable_exception() as cm: obj = _lsprof.Profiler(lambda: int) obj.enable() obj = _lsprof.Profiler(1) obj.disable() obj.clear() self.assertEqual(cm.unraisable.exc_type, TypeError)
def test_unraisable(self): # Issue #22836: PyErr_WriteUnraisable() should give sensible reports class BrokenDel: def __del__(self): exc = ValueError("del is broken") # The following line is included in the traceback report: raise exc obj = BrokenDel() with support.catch_unraisable_exception() as cm: del obj self.assertEqual(cm.unraisable.object, BrokenDel.__del__) self.assertIsNotNone(cm.unraisable.exc_traceback)
def test_atexit_with_unregistered_function(self): # See bpo-46025 for more info def func(): atexit.unregister(func) 1/0 atexit.register(func) try: with support.catch_unraisable_exception() as cm: atexit._run_exitfuncs() self.assertEqual(cm.unraisable.object, func) self.assertEqual(cm.unraisable.exc_type, ZeroDivisionError) self.assertEqual(type(cm.unraisable.exc_value), ZeroDivisionError) finally: atexit.unregister(func)
def test_convert_result_error(self): def func(): return ("tuple", ) proto = CFUNCTYPE(c_int) ctypes_func = proto(func) with support.catch_unraisable_exception() as cm: # don't test the result since it is an uninitialized value result = ctypes_func() self.assertIsInstance(cm.unraisable.exc_value, TypeError) self.assertEqual( cm.unraisable.err_msg, "Exception ignored on converting result " "of ctypes callback function") self.assertIs(cm.unraisable.object, func)
def test_unraisable_exception(self): def task(): started.release() raise ValueError("task failed") started = thread.allocate_lock() with support.catch_unraisable_exception() as cm: with support.wait_threads_exit(): started.acquire() thread.start_new_thread(task, ()) started.acquire() self.assertEqual(str(cm.unraisable.exc_value), "task failed") self.assertIs(cm.unraisable.object, task) self.assertEqual(cm.unraisable.err_msg, "Exception ignored in thread started by") self.assertIsNotNone(cm.unraisable.exc_traceback)
def test_reentrancy(self): def foo(*args): ... def bar(*args): ... class A: def __call__(self, *args): pass def __del__(self): sys.setprofile(bar) sys.setprofile(A()) with support.catch_unraisable_exception() as cm: sys.setprofile(foo) self.assertEqual(cm.unraisable.object, A.__del__) self.assertIsInstance(cm.unraisable.exc_value, RuntimeError) self.assertEqual(sys.getprofile(), foo)