Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The most compatible way to fix #2020 seems to be just preventing assigning __class__ in the first place. We still make sure there is a valid _main_thread that is-a _MainThread though.
- Loading branch information
Showing
4 changed files
with
189 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Tests for `issue 2020 <https://github.com/gevent/gevent/issues/2020>`_: | ||
3.11.8 and 3.12.2 try to swizzle ``__class__`` of the dummy thread | ||
found when forking from inside a greenlet. | ||
""" | ||
from gevent import monkey; monkey.patch_all() # pragma: testrunner-no-monkey-combine | ||
|
||
import unittest | ||
import gevent.testing as greentest | ||
|
||
import tempfile | ||
|
||
@greentest.skipOnWindows("Uses os.fork") | ||
class Test(greentest.TestCase): | ||
|
||
|
||
def test_fork_from_dummy_thread(self): | ||
import os | ||
import threading | ||
import contextlib | ||
|
||
import gevent | ||
|
||
def do_it(out): | ||
# Be sure we've put the DummyThread in the threading | ||
# maps | ||
assert isinstance(threading.current_thread(), threading._DummyThread) | ||
|
||
with open(out, 'wt', encoding='utf-8') as f: | ||
with contextlib.redirect_stderr(f): | ||
r = os.fork() | ||
if r == 0: | ||
# In the child. | ||
# Our stderr redirect above will capture the | ||
# "Exception ignored in _after_fork()" that the interpreter | ||
# prints; actually printing the main_thread will result in | ||
# raising an exception if our patch doesn't work. | ||
main = threading.main_thread() | ||
print(main, file=f) | ||
print(type(main), file=f) | ||
return r | ||
|
||
with tempfile.NamedTemporaryFile('w+t', suffix='.gevent_threading.txt') as tf: | ||
glet = gevent.spawn(do_it, tf.name) | ||
glet.join() | ||
pid = glet.get() | ||
if pid == 0: | ||
# Dump the child process quickly | ||
os._exit(0) | ||
|
||
os.waitpid(pid, 0) | ||
tf.seek(0, 0) | ||
contents = tf.read() | ||
|
||
|
||
self.assertIn("<class 'threading._MainThread'>", contents) | ||
self.assertNotIn("_DummyThread", contents) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters