Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

86 řádky
3.0KB

  1. import unittest
  2. import sys
  3. import gc
  4. import time
  5. import weakref
  6. import greenlet
  7. import threading
  8. class ArgRefcountTests(unittest.TestCase):
  9. def test_arg_refs(self):
  10. args = ('a', 'b', 'c')
  11. refcount_before = sys.getrefcount(args)
  12. g = greenlet.greenlet(
  13. lambda *args: greenlet.getcurrent().parent.switch(*args))
  14. for i in range(100):
  15. g.switch(*args)
  16. self.assertEqual(sys.getrefcount(args), refcount_before)
  17. def test_kwarg_refs(self):
  18. kwargs = {}
  19. g = greenlet.greenlet(
  20. lambda **kwargs: greenlet.getcurrent().parent.switch(**kwargs))
  21. for i in range(100):
  22. g.switch(**kwargs)
  23. self.assertEqual(sys.getrefcount(kwargs), 2)
  24. if greenlet.GREENLET_USE_GC:
  25. # These only work with greenlet gc support
  26. def recycle_threads(self):
  27. # By introducing a thread that does sleep we allow other threads,
  28. # that have triggered their __block condition, but did not have a
  29. # chance to deallocate their thread state yet, to finally do so.
  30. # The way it works is by requiring a GIL switch (different thread),
  31. # which does a GIL release (sleep), which might do a GIL switch
  32. # to finished threads and allow them to clean up.
  33. def worker():
  34. time.sleep(0.001)
  35. t = threading.Thread(target=worker)
  36. t.start()
  37. time.sleep(0.001)
  38. t.join()
  39. def test_threaded_leak(self):
  40. gg = []
  41. def worker():
  42. # only main greenlet present
  43. gg.append(weakref.ref(greenlet.getcurrent()))
  44. for i in range(2):
  45. t = threading.Thread(target=worker)
  46. t.start()
  47. t.join()
  48. del t
  49. greenlet.getcurrent() # update ts_current
  50. self.recycle_threads()
  51. greenlet.getcurrent() # update ts_current
  52. gc.collect()
  53. greenlet.getcurrent() # update ts_current
  54. for g in gg:
  55. self.assertTrue(g() is None)
  56. def test_threaded_adv_leak(self):
  57. gg = []
  58. def worker():
  59. # main and additional *finished* greenlets
  60. ll = greenlet.getcurrent().ll = []
  61. def additional():
  62. ll.append(greenlet.getcurrent())
  63. for i in range(2):
  64. greenlet.greenlet(additional).switch()
  65. gg.append(weakref.ref(greenlet.getcurrent()))
  66. for i in range(2):
  67. t = threading.Thread(target=worker)
  68. t.start()
  69. t.join()
  70. del t
  71. greenlet.getcurrent() # update ts_current
  72. self.recycle_threads()
  73. greenlet.getcurrent() # update ts_current
  74. gc.collect()
  75. greenlet.getcurrent() # update ts_current
  76. for g in gg:
  77. self.assertTrue(g() is None)