您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

86 行
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)