]>
Commit | Line | Data |
---|---|---|
5a03dc88 JB |
1 | Based on https://github.com/gevent/gevent/commit/8224e81425762ad21d3b63ffb9cc0a0c2d789704.patch |
2 | and https://src.fedoraproject.org/rpms/python-gevent/raw/master/f/0001-code-replace.patch | |
3 | ||
4 | From e6e2959184909c6292e0135b709282cd5f96065b Mon Sep 17 00:00:00 2001 | |
5 | From: Jason Madden <jamadden@gmail.com> | |
6 | Date: Fri, 6 Sep 2019 16:29:58 -0500 | |
7 | Subject: [PATCH 1/9] Basic support for CPython 3.8.0b4. | |
8 | ||
9 | Still needs the specific networking test classes added, but all the basics pass for me. Lets see about CI. | |
10 | --- | |
11 | .travis.yml | 11 +++++++ | |
12 | CHANGES.rst | 4 +++ | |
13 | examples/webproxy.py | 7 +++- | |
14 | pyproject.toml | 5 +-- | |
15 | scripts/install.sh | 3 ++ | |
16 | src/gevent/__semaphore.pxd | 2 +- | |
17 | src/gevent/_compat.py | 2 +- | |
18 | src/gevent/_socket2.py | 1 + | |
19 | src/gevent/_socketcommon.py | 12 +++++-- | |
20 | src/gevent/monkey.py | 46 +++++++++++++++++++++++++-- | |
21 | src/gevent/os.py | 29 ++++++++++++++--- | |
22 | src/gevent/subprocess.py | 32 +++++++++++++++++++ | |
23 | src/gevent/testing/testrunner.py | 17 +++++++--- | |
24 | src/gevent/tests/test__core_fork.py | 7 ++-- | |
25 | src/gevent/tests/test__threading_2.py | 26 +++++++++------ | |
26 | src/gevent/thread.py | 6 ++++ | |
27 | src/gevent/threading.py | 46 ++++++++++----------------- | |
28 | 17 files changed, 196 insertions(+), 60 deletions(-) | |
29 | ||
30 | #diff --git a/.travis.yml b/.travis.yml | |
31 | #index bf307df95..05dc24b12 100644 | |
32 | #--- a/.travis.yml | |
33 | #+++ b/.travis.yml | |
34 | #@@ -42,6 +42,7 @@ env: | |
35 | # - TRAVIS_PYTHON_VERSION=3.5 | |
36 | # - TRAVIS_PYTHON_VERSION=3.6 | |
37 | # - TRAVIS_PYTHON_VERSION=3.7 | |
38 | #+ - TRAVIS_PYTHON_VERSION=3.8 | |
39 | # - TRAVIS_PYTHON_VERSION=pypy2.7 | |
40 | # - TRAVIS_PYTHON_VERSION=pypy3.6 | |
41 | # - TRAVIS_PYTHON_VERSION=2.7 GEVENTSETUP_EMBED=0 | |
42 | #@@ -144,6 +145,8 @@ jobs: | |
43 | # script: ccache -s | |
44 | # before_script: true | |
45 | # after_success: true | |
46 | #+ - <<: *build-gevent | |
47 | #+ env: TRAVIS_PYTHON_VERSION=3.8 | |
48 | # - <<: *build-gevent | |
49 | # env: TRAVIS_PYTHON_VERSION=3.5 | |
50 | # - <<: *build-gevent | |
51 | #@@ -278,6 +281,14 @@ jobs: | |
52 | # env: TRAVIS_PYTHON_VERSION=3.7 | |
53 | # name: pure37 | |
54 | # | |
55 | #+ # 3.8 | |
56 | #+ - <<: *test-libuv-jobs | |
57 | #+ env: TRAVIS_PYTHON_VERSION=3.8 | |
58 | #+ name: libuv36 | |
59 | #+ - <<: *test-libev-jobs | |
60 | #+ env: TRAVIS_PYTHON_VERSION=3.8 | |
61 | #+ name: libev-cffi36 | |
62 | #+ | |
63 | # | |
64 | # # 2.7, no-embed. Run the tests that exercise the libraries we | |
65 | # # linked to. | |
66 | #diff --git a/CHANGES.rst b/CHANGES.rst | |
67 | #index 52b5e1c6f..53f4398d2 100644 | |
68 | #--- a/CHANGES.rst | |
69 | #+++ b/CHANGES.rst | |
70 | #@@ -12,6 +12,10 @@ | |
71 | # - Add an ``--module`` option to ``gevent.monkey`` allowing to run a Python | |
72 | # module rather than a script. See :pr:`1440`. | |
73 | # | |
74 | #+- Add support for CPython 3.8.0b4. | |
75 | #+ | |
76 | #+- Improve the way joining the main thread works on Python 3. | |
77 | #+ | |
78 | # 1.5a1 (2019-05-02) | |
79 | # ================== | |
80 | # | |
3c6d899b AM |
81 | diff -urNp -x '*.orig' gevent-1.4.0.org/examples/webproxy.py gevent-1.4.0/examples/webproxy.py |
82 | --- gevent-1.4.0.org/examples/webproxy.py 2019-01-04 12:51:44.000000000 +0100 | |
83 | +++ gevent-1.4.0/examples/webproxy.py 2021-03-05 09:44:15.299051013 +0100 | |
84 | @@ -15,7 +15,12 @@ from gevent import monkey; monkey.patch_ | |
5a03dc88 JB |
85 | import sys |
86 | import re | |
87 | import traceback | |
88 | -from cgi import escape | |
89 | + | |
90 | +try: | |
91 | + from cgi import escape | |
92 | +except ImportError: | |
93 | + # Python 3.8 removed this API | |
94 | + from html import escape | |
95 | ||
96 | try: | |
97 | import urllib2 | |
3c6d899b AM |
98 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/__semaphore.pxd gevent-1.4.0/src/gevent/__semaphore.pxd |
99 | --- gevent-1.4.0.org/src/gevent/__semaphore.pxd 2019-01-04 12:51:44.000000000 +0100 | |
100 | +++ gevent-1.4.0/src/gevent/__semaphore.pxd 2021-03-05 09:44:15.299051013 +0100 | |
5a03dc88 JB |
101 | @@ -13,7 +13,7 @@ cdef class Semaphore(AbstractLinkable): |
102 | # threadpool uses it | |
103 | cpdef _start_notify(self) | |
104 | cpdef int wait(self, object timeout=*) except -1000 | |
105 | - cpdef bint acquire(self, int blocking=*, object timeout=*) except -1000 | |
106 | + cpdef bint acquire(self, bint blocking=*, object timeout=*) except -1000 | |
107 | cpdef __enter__(self) | |
108 | cpdef __exit__(self, object t, object v, object tb) | |
109 | ||
3c6d899b AM |
110 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/_compat.py gevent-1.4.0/src/gevent/_compat.py |
111 | --- gevent-1.4.0.org/src/gevent/_compat.py 2019-01-04 12:51:44.000000000 +0100 | |
112 | +++ gevent-1.4.0/src/gevent/_compat.py 2021-03-05 09:44:15.299051013 +0100 | |
113 | @@ -14,7 +14,7 @@ PY3 = sys.version_info[0] >= 3 | |
5a03dc88 JB |
114 | PYPY = hasattr(sys, 'pypy_version_info') |
115 | WIN = sys.platform.startswith("win") | |
116 | LINUX = sys.platform.startswith('linux') | |
117 | -OSX = sys.platform == 'darwin' | |
118 | +OSX = MAC = sys.platform == 'darwin' | |
119 | ||
120 | ||
121 | PURE_PYTHON = PYPY or os.getenv('PURE_PYTHON') | |
3c6d899b AM |
122 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/_socket2.py gevent-1.4.0/src/gevent/_socket2.py |
123 | --- gevent-1.4.0.org/src/gevent/_socket2.py 2019-01-04 12:51:44.000000000 +0100 | |
124 | +++ gevent-1.4.0/src/gevent/_socket2.py 2021-03-05 09:44:15.299051013 +0100 | |
125 | @@ -6,6 +6,7 @@ from __future__ import absolute_import | |
5a03dc88 JB |
126 | |
127 | # Our import magic sadly makes this warning useless | |
128 | # pylint: disable=undefined-variable | |
129 | +import sys | |
130 | ||
131 | from gevent import _socketcommon | |
132 | from gevent._util import copy_globals | |
3c6d899b AM |
133 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/_socketcommon.py gevent-1.4.0/src/gevent/_socketcommon.py |
134 | --- gevent-1.4.0.org/src/gevent/_socketcommon.py 2019-01-04 12:51:44.000000000 +0100 | |
135 | +++ gevent-1.4.0/src/gevent/_socketcommon.py 2021-03-05 09:44:15.302384451 +0100 | |
136 | @@ -74,6 +74,12 @@ from gevent._hub_local import get_hub_no | |
137 | from gevent._compat import string_types, integer_types, PY3 | |
138 | from gevent._util import copy_globals | |
139 | ||
140 | +if sys.version_info[:2] >= (3, 8): | |
141 | + __imports__.extend([ | |
142 | + 'create_server', | |
143 | + 'has_dualstack_ipv6' | |
144 | + ]) | |
145 | + | |
146 | is_windows = sys.platform == 'win32' | |
147 | is_macos = sys.platform == 'darwin' | |
148 | ||
149 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/_ssl3.py gevent-1.4.0/src/gevent/_ssl3.py | |
150 | --- gevent-1.4.0.org/src/gevent/_ssl3.py 2019-01-04 12:51:44.000000000 +0100 | |
151 | +++ gevent-1.4.0/src/gevent/_ssl3.py 2021-03-05 09:44:15.299051013 +0100 | |
152 | @@ -667,6 +667,11 @@ class SSLSocket(socket): | |
153 | return None | |
154 | return self._sslobj.tls_unique_cb() | |
155 | ||
156 | + def verify_client_post_handshake(self): | |
157 | + # Only present in 3.7.1+; an attributeerror is alright | |
158 | + if self._sslobj: | |
159 | + return self._sslobj.verify_client_post_handshake() | |
160 | + raise ValueError("No SSL wrapper around " + str(self)) | |
161 | ||
162 | # Python does not support forward declaration of types | |
163 | SSLContext.sslsocket_class = SSLSocket | |
164 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/_tblib.py gevent-1.4.0/src/gevent/_tblib.py | |
165 | --- gevent-1.4.0.org/src/gevent/_tblib.py 2019-01-04 12:51:44.000000000 +0100 | |
166 | +++ gevent-1.4.0/src/gevent/_tblib.py 2021-03-05 09:44:15.302384451 +0100 | |
167 | @@ -198,7 +198,10 @@ class Traceback(object): | |
168 | while current: | |
169 | f_code = current.tb_frame.f_code | |
170 | code = compile('\n' * (current.tb_lineno - 1) + 'raise __traceback_maker', current.tb_frame.f_code.co_filename, 'exec') | |
171 | - if PY3: | |
172 | + if hasattr(code, "replace"): | |
173 | + # Python 3.8 and newer | |
174 | + code = code.replace(co_argcount=0, co_freevars=(), co_cellvars=()) | |
175 | + elif PY3: | |
176 | code = CodeType( | |
177 | 0, code.co_kwonlyargcount, | |
178 | code.co_nlocals, code.co_stacksize, code.co_flags, | |
179 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/libuv/_corecffi_source.c gevent-1.4.0/src/gevent/libuv/_corecffi_source.c | |
180 | --- gevent-1.4.0.org/src/gevent/libuv/_corecffi_source.c 2019-01-04 12:51:44.000000000 +0100 | |
181 | +++ gevent-1.4.0/src/gevent/libuv/_corecffi_source.c 2021-03-05 09:44:15.299051013 +0100 | |
182 | @@ -150,32 +150,34 @@ static void _gevent_fs_poll_callback3(vo | |
183 | ||
184 | static void gevent_uv_walk_callback_close(uv_handle_t* handle, void* arg) | |
185 | { | |
186 | - if( handle && !uv_is_closing(handle) ) { | |
187 | - uv_close(handle, NULL); | |
188 | - } | |
189 | + if( handle && !uv_is_closing(handle) ) { | |
190 | + uv_close(handle, NULL); | |
191 | + } | |
192 | } | |
193 | ||
194 | static void gevent_close_all_handles(uv_loop_t* loop) | |
195 | { | |
196 | + if (loop) { | |
197 | uv_walk(loop, gevent_uv_walk_callback_close, NULL); | |
198 | + } | |
199 | } | |
200 | ||
201 | static void gevent_zero_timer(uv_timer_t* handle) | |
202 | { | |
203 | - memset(handle, 0, sizeof(uv_timer_t)); | |
204 | + memset(handle, 0, sizeof(uv_timer_t)); | |
205 | } | |
206 | ||
207 | static void gevent_zero_check(uv_check_t* handle) | |
208 | { | |
209 | - memset(handle, 0, sizeof(uv_check_t)); | |
210 | + memset(handle, 0, sizeof(uv_check_t)); | |
211 | } | |
212 | ||
213 | static void gevent_zero_prepare(uv_prepare_t* handle) | |
214 | { | |
215 | - memset(handle, 0, sizeof(uv_prepare_t)); | |
216 | + memset(handle, 0, sizeof(uv_prepare_t)); | |
217 | } | |
218 | ||
219 | static void gevent_zero_loop(uv_loop_t* handle) | |
220 | { | |
221 | - memset(handle, 0, sizeof(uv_loop_t)); | |
222 | + memset(handle, 0, sizeof(uv_loop_t)); | |
223 | } | |
224 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/monkey.py gevent-1.4.0/src/gevent/monkey.py | |
225 | --- gevent-1.4.0.org/src/gevent/monkey.py 2019-01-04 12:51:44.000000000 +0100 | |
226 | +++ gevent-1.4.0/src/gevent/monkey.py 2021-03-05 09:44:15.299051013 +0100 | |
227 | @@ -614,6 +614,22 @@ def patch_thread(threading=True, _thread | |
5a03dc88 JB |
228 | raise RuntimeError("Cannot join current thread") |
229 | if thread_greenlet is not None and thread_greenlet.dead: | |
230 | return | |
231 | + # You may ask: Why not call thread_greenlet.join()? | |
232 | + # Well, in the one case we actually have a greenlet, it's the | |
233 | + # low-level greenlet.greenlet object for the main thread, which | |
234 | + # doesn't have a join method. | |
235 | + # | |
236 | + # You may ask: Why not become the main greenlet's *parent* | |
237 | + # so you can get notified when it finishes? Because you can't | |
238 | + # create a greenlet cycle (the current greenlet is a descendent | |
239 | + # of the parent), and nor can you set a greenlet's parent to None, | |
240 | + # so there can only ever be one greenlet with a parent of None: the main | |
241 | + # greenlet, the one we need to watch. | |
242 | + # | |
243 | + # You may ask: why not swizzle out the problematic lock on the main thread | |
244 | + # into a gevent friendly lock? Well, the interpreter actually depends on that | |
245 | + # for the main thread in threading._shutdown; see below. | |
246 | + | |
247 | if not thread.is_alive(): | |
248 | return | |
249 | ||
3c6d899b | 250 | @@ -646,8 +662,34 @@ def patch_thread(threading=True, _thread |
5a03dc88 JB |
251 | if orig_current_thread == threading_mod.main_thread(): |
252 | main_thread = threading_mod.main_thread() | |
253 | _greenlet = main_thread._greenlet = greenlet.getcurrent() | |
5a03dc88 JB |
254 | + main_thread.__real_tstate_lock = main_thread._tstate_lock |
255 | + | |
256 | + # The interpreter will call threading._shutdown | |
257 | + # when the main thread exits and is about to | |
258 | + # go away. It is called *in* the main thread. This | |
259 | + # is a perfect place to notify other greenlets that | |
260 | + # the main thread is done. We do this by overriding the | |
261 | + # lock of the main thread during operation, and only restoring | |
262 | + # it to the native blocking version at shutdown time | |
263 | + # (the interpreter also has a reference to this lock in a | |
264 | + # C data structure). | |
265 | + main_thread._tstate_lock = threading_mod.Lock() | |
266 | + main_thread._tstate_lock.acquire() | |
267 | + orig_shutdown = threading_mod._shutdown | |
268 | + def _shutdown(): | |
269 | + # Release anyone trying to join() me, | |
270 | + # and let us switch to them. | |
271 | + if main_thread._tstate_lock: | |
272 | + main_thread._tstate_lock.release() | |
273 | + from gevent import sleep | |
274 | + sleep() | |
275 | + # The only truly blocking native shutdown lock to | |
276 | + # acquire should be our own (hopefully) | |
277 | + main_thread._tstate_lock = main_thread.__real_tstate_lock | |
278 | + main_thread.__real_tstate_lock = None | |
279 | + orig_shutdown() | |
3c6d899b AM |
280 | |
281 | - main_thread.join = make_join_func(main_thread, _greenlet) | |
5a03dc88 JB |
282 | + threading_mod._shutdown = _shutdown |
283 | ||
284 | # Patch up the ident of the main thread to match. This | |
285 | # matters if threading was imported before monkey-patching | |
3c6d899b AM |
286 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/os.py gevent-1.4.0/src/gevent/os.py |
287 | --- gevent-1.4.0.org/src/gevent/os.py 2019-01-04 12:51:44.000000000 +0100 | |
288 | +++ gevent-1.4.0/src/gevent/os.py 2021-03-05 09:44:15.299051013 +0100 | |
289 | @@ -385,6 +385,12 @@ if hasattr(os, 'fork'): | |
5a03dc88 JB |
290 | # we're not watching it |
291 | return _waitpid(pid, options) | |
292 | ||
293 | + def _watch_child(pid, callback=None, loop=None, ref=False): | |
294 | + loop = loop or get_hub().loop | |
295 | + watcher = loop.child(pid, ref=ref) | |
296 | + _watched_children[pid] = watcher | |
297 | + watcher.start(_on_child, watcher, callback) | |
298 | + | |
299 | def fork_and_watch(callback=None, loop=None, ref=False, fork=fork_gevent): | |
300 | """ | |
301 | Fork a child process and start a child watcher for it in the parent process. | |
3c6d899b | 302 | @@ -413,10 +419,7 @@ if hasattr(os, 'fork'): |
5a03dc88 JB |
303 | pid = fork() |
304 | if pid: | |
305 | # parent | |
306 | - loop = loop or get_hub().loop | |
307 | - watcher = loop.child(pid, ref=ref) | |
308 | - _watched_children[pid] = watcher | |
309 | - watcher.start(_on_child, watcher, callback) | |
310 | + _watch_child(pid, callback, loop, ref) | |
311 | return pid | |
312 | ||
313 | __extensions__.append('fork_and_watch') | |
3c6d899b | 314 | @@ -474,6 +477,23 @@ if hasattr(os, 'fork'): |
5a03dc88 JB |
315 | # take any args to match fork_and_watch |
316 | return forkpty_and_watch(*args, **kwargs) | |
317 | __implements__.append("waitpid") | |
318 | + | |
319 | + if hasattr(os, 'posix_spawn'): | |
320 | + _raw_posix_spawn = os.posix_spawn | |
321 | + _raw_posix_spawnp = os.posix_spawnp | |
322 | + | |
323 | + def posix_spawn(*args, **kwargs): | |
324 | + pid = _raw_posix_spawn(*args, **kwargs) | |
325 | + _watch_child(pid) | |
326 | + return pid | |
327 | + | |
328 | + def posix_spawnp(*args, **kwargs): | |
329 | + pid = _raw_posix_spawnp(*args, **kwargs) | |
330 | + _watch_child(pid) | |
331 | + return pid | |
332 | + | |
333 | + __implements__.append("posix_spawn") | |
334 | + __implements__.append("posix_spawnp") | |
335 | else: | |
336 | def fork(): | |
337 | """ | |
3c6d899b | 338 | @@ -503,6 +523,7 @@ if hasattr(os, 'fork'): |
5a03dc88 JB |
339 | else: |
340 | __implements__.remove('fork') | |
341 | ||
342 | + | |
343 | __imports__ = copy_globals(os, globals(), | |
344 | names_to_ignore=__implements__ + __extensions__, | |
345 | dunder_names_to_keep=()) | |
3c6d899b AM |
346 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/testing/testrunner.py gevent-1.4.0/src/gevent/testing/testrunner.py |
347 | --- gevent-1.4.0.org/src/gevent/testing/testrunner.py 2019-01-04 12:51:44.000000000 +0100 | |
348 | +++ gevent-1.4.0/src/gevent/testing/testrunner.py 2021-03-05 09:44:15.299051013 +0100 | |
349 | @@ -381,17 +381,26 @@ def _setup_environ(debug=False): | |
5a03dc88 JB |
350 | if 'GEVENT_DEBUG' not in os.environ and debug: |
351 | os.environ['GEVENT_DEBUG'] = 'debug' | |
352 | ||
353 | - if 'PYTHONTRACEMALLOC' not in os.environ: | |
354 | + if 'PYTHONTRACEMALLOC' not in os.environ and debug: | |
355 | + # This slows the tests down quite a bit. Reserve | |
356 | + # for debugging. | |
357 | os.environ['PYTHONTRACEMALLOC'] = '10' | |
358 | ||
359 | if 'PYTHONDEVMODE' not in os.environ: | |
360 | - # Python 3.7 | |
361 | + # Python 3.7 and above. | |
362 | os.environ['PYTHONDEVMODE'] = '1' | |
363 | ||
364 | - if 'PYTHONMALLOC' not in os.environ: | |
365 | - # Python 3.6 | |
366 | + if 'PYTHONMALLOC' not in os.environ and debug: | |
367 | + # Python 3.6 and above. | |
368 | + # This slows the tests down some, but | |
369 | + # can detect memory corruption. Unfortunately | |
370 | + # it can also be flaky, especially in pre-release | |
371 | + # versions of Python (e.g., lots of crashes on Python 3.8b4). | |
372 | os.environ['PYTHONMALLOC'] = 'debug' | |
373 | ||
374 | + if sys.version_info.releaselevel != 'final' and not debug: | |
375 | + os.environ['PYTHONMALLOC'] = 'default' | |
376 | + os.environ['PYTHONDEVMODE'] = '' | |
377 | ||
378 | ||
379 | def main(): | |
3c6d899b AM |
380 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/tests/known_failures.py gevent-1.4.0/src/gevent/tests/known_failures.py |
381 | --- gevent-1.4.0.org/src/gevent/tests/known_failures.py 2021-03-05 09:44:15.072377256 +0100 | |
382 | +++ gevent-1.4.0/src/gevent/tests/known_failures.py 2021-03-05 09:44:15.302384451 +0100 | |
383 | @@ -610,6 +610,15 @@ RUN_ALONE = [ | |
384 | 'test__examples.py', | |
385 | ] | |
386 | ||
387 | +if APPVEYOR: | |
388 | + # Strange failures sometimes, but only on Python 3.7, reporting | |
389 | + # "ConnectionAbortedError: [WinError 10053] An established | |
390 | + # connection was aborted by the software in your host machine" | |
391 | + # when we've done no such thing. Try running not in parallel | |
392 | + RUN_ALONE += [ | |
393 | + 'test__ssl.py', | |
394 | + 'test__server.py', | |
395 | + ] | |
396 | ||
397 | ||
398 | if APPVEYOR or TRAVIS: | |
399 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/tests/test__core.py gevent-1.4.0/src/gevent/tests/test__core.py | |
400 | --- gevent-1.4.0.org/src/gevent/tests/test__core.py 2019-01-04 12:51:44.000000000 +0100 | |
401 | +++ gevent-1.4.0/src/gevent/tests/test__core.py 2021-03-05 09:44:15.299051013 +0100 | |
402 | @@ -2,6 +2,7 @@ | |
403 | from __future__ import absolute_import, print_function, division | |
404 | import sys | |
405 | import unittest | |
406 | +import sys | |
407 | import gevent.testing as greentest | |
408 | ||
409 | from gevent import core | |
410 | @@ -130,6 +131,12 @@ class TestWatchersDefault(TestWatchers): | |
411 | "See https://ci.appveyor.com/project/denik/gevent/build/1.0.1380/job/lrlvid6mkjtyrhn5#L1103 " | |
412 | "It has also timed out, but only on Appveyor CPython 3.6; local CPython 3.6 does not. " | |
413 | "See https://ci.appveyor.com/project/denik/gevent/build/1.0.1414/job/yn7yi8b53vtqs8lw#L1523") | |
414 | +@greentest.skipIf( | |
415 | + greentest.LIBUV and greentest.RUNNING_ON_TRAVIS and sys.version_info == (3, 8, 0, 'beta', 4), | |
416 | + "Crashes on 3.8.0b4 on TravisCI. " | |
417 | + "(https://travis-ci.org/gevent/gevent/jobs/582031266#L215) " | |
418 | + "Unable to reproduce locally so far on macOS." | |
419 | +) | |
420 | class TestWatchersDefaultDestroyed(TestWatchers): | |
421 | ||
422 | def _makeOne(self): | |
423 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/tests/test__core_fork.py gevent-1.4.0/src/gevent/tests/test__core_fork.py | |
424 | --- gevent-1.4.0.org/src/gevent/tests/test__core_fork.py 2019-01-04 12:51:44.000000000 +0100 | |
425 | +++ gevent-1.4.0/src/gevent/tests/test__core_fork.py 2021-03-05 09:44:15.299051013 +0100 | |
426 | @@ -1,11 +1,12 @@ | |
5a03dc88 JB |
427 | from __future__ import print_function |
428 | import gevent.monkey | |
429 | gevent.monkey.patch_all() | |
430 | -import gevent | |
431 | -import os | |
432 | ||
433 | +import os | |
434 | import multiprocessing | |
435 | ||
436 | +import gevent | |
5a03dc88 JB |
437 | + |
438 | hub = gevent.get_hub() | |
439 | pid = os.getpid() | |
440 | newpid = None | |
3c6d899b | 441 | @@ -46,6 +47,7 @@ def test(): |
5a03dc88 JB |
442 | if __name__ == '__main__': |
443 | # Must call for Windows to fork properly; the fork can't be in the top-level | |
444 | multiprocessing.freeze_support() | |
445 | + | |
446 | # fork watchers weren't firing in multi-threading processes. | |
447 | # This test is designed to prove that they are. | |
448 | # However, it fails on Windows: The fork watcher never runs! | |
3c6d899b AM |
449 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/tests/test__greenness.py gevent-1.4.0/src/gevent/tests/test__greenness.py |
450 | --- gevent-1.4.0.org/src/gevent/tests/test__greenness.py 2019-01-04 12:51:44.000000000 +0100 | |
451 | +++ gevent-1.4.0/src/gevent/tests/test__greenness.py 2021-03-05 09:44:15.299051013 +0100 | |
452 | @@ -29,13 +29,15 @@ monkey.patch_all() | |
453 | import gevent.testing as greentest | |
454 | ||
455 | try: | |
456 | - import urllib2 | |
457 | -except ImportError: | |
458 | from urllib import request as urllib2 | |
459 | -try: | |
460 | - import BaseHTTPServer | |
461 | -except ImportError: | |
462 | from http import server as BaseHTTPServer | |
463 | + from http.server import SimpleHTTPRequestHandler | |
464 | +except ImportError: | |
465 | + # Python 2 | |
466 | + import urllib2 | |
467 | + import BaseHTTPServer | |
468 | + from SimpleHTTPServer import SimpleHTTPRequestHandler | |
469 | + | |
470 | ||
471 | import gevent | |
472 | from gevent.testing import params | |
473 | @@ -47,7 +49,8 @@ class TestGreenness(greentest.TestCase): | |
474 | def setUp(self): | |
475 | server_address = params.DEFAULT_BIND_ADDR_TUPLE | |
476 | BaseHTTPServer.BaseHTTPRequestHandler.protocol_version = "HTTP/1.0" | |
477 | - self.httpd = BaseHTTPServer.HTTPServer(server_address, BaseHTTPServer.BaseHTTPRequestHandler) | |
478 | + self.httpd = BaseHTTPServer.HTTPServer(server_address, | |
479 | + SimpleHTTPRequestHandler) | |
480 | self.httpd.request_count = 0 | |
481 | ||
482 | def tearDown(self): | |
483 | @@ -62,10 +65,10 @@ class TestGreenness(greentest.TestCase): | |
484 | server = gevent.spawn(self.serve) | |
485 | ||
486 | port = self.httpd.socket.getsockname()[1] | |
487 | - with self.assertRaises(urllib2.HTTPError) as exc: | |
488 | - urllib2.urlopen('http://127.0.0.1:%s' % port) | |
489 | - self.assertEqual(exc.exception.code, 501) | |
490 | - server.get(0.01) | |
491 | + rsp = urllib2.urlopen('http://127.0.0.1:%s' % port) | |
492 | + rsp.read() | |
493 | + rsp.close() | |
494 | + server.join() | |
495 | self.assertEqual(self.httpd.request_count, 1) | |
496 | ||
497 | ||
498 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/tests/test__threading_2.py gevent-1.4.0/src/gevent/tests/test__threading_2.py | |
499 | --- gevent-1.4.0.org/src/gevent/tests/test__threading_2.py 2019-01-04 12:51:44.000000000 +0100 | |
500 | +++ gevent-1.4.0/src/gevent/tests/test__threading_2.py 2021-03-05 09:44:15.299051013 +0100 | |
501 | @@ -33,6 +33,7 @@ try: | |
5a03dc88 JB |
502 | from test.support import verbose |
503 | except ImportError: | |
504 | from test.test_support import verbose | |
505 | + | |
506 | import random | |
507 | import re | |
508 | import sys | |
3c6d899b | 509 | @@ -46,7 +47,7 @@ import unittest |
5a03dc88 JB |
510 | import weakref |
511 | ||
512 | from gevent.tests import lock_tests | |
513 | - | |
514 | +verbose = False | |
515 | # A trivial mutable counter. | |
516 | ||
517 | def skipDueToHang(cls): | |
3c6d899b | 518 | @@ -132,7 +133,7 @@ class ThreadTests(unittest.TestCase): |
5a03dc88 JB |
519 | print('waiting for all tasks to complete') |
520 | for t in threads: | |
521 | t.join(NUMTASKS) | |
522 | - self.assertFalse(t.is_alive()) | |
523 | + self.assertFalse(t.is_alive(), t.__dict__) | |
524 | if hasattr(t, 'ident'): | |
525 | self.assertNotEqual(t.ident, 0) | |
526 | self.assertFalse(t.ident is None) | |
3c6d899b | 527 | @@ -351,28 +352,33 @@ class ThreadTests(unittest.TestCase): |
5a03dc88 JB |
528 | # Issue 1722344 |
529 | # Raising SystemExit skipped threading._shutdown | |
530 | import subprocess | |
531 | - p = subprocess.Popen([sys.executable, "-W", "ignore", "-c", """if 1: | |
532 | + script = """if 1: | |
533 | %s | |
534 | import threading | |
535 | from time import sleep | |
536 | ||
537 | def child(): | |
538 | - sleep(1) | |
539 | + sleep(0.3) | |
540 | # As a non-daemon thread we SHOULD wake up and nothing | |
541 | # should be torn down yet | |
542 | - print("Woke up, sleep function is: %%r" %% sleep) | |
543 | + print("Woke up, sleep function is: %%s.%%s" %% (sleep.__module__, sleep.__name__)) | |
544 | ||
545 | threading.Thread(target=child).start() | |
546 | raise SystemExit | |
547 | - """ % setup_4], | |
548 | + """ % setup_4 | |
549 | + p = subprocess.Popen([sys.executable, "-W", "ignore", "-c", script], | |
550 | stdout=subprocess.PIPE, | |
551 | stderr=subprocess.PIPE) | |
552 | stdout, stderr = p.communicate() | |
553 | stdout = stdout.strip() | |
554 | stdout = stdout.decode('utf-8') | |
555 | stderr = stderr.decode('utf-8') | |
556 | - assert re.match('^Woke up, sleep function is: <.*?sleep.*?>$', stdout), repr(stdout) | |
557 | - stderr = re.sub(r"^\[\d+ refs\]", "", stderr, re.MULTILINE).strip() | |
558 | + | |
559 | + | |
560 | + self.assertEqual( | |
561 | + 'Woke up, sleep function is: gevent.hub.sleep', | |
562 | + stdout) | |
563 | + | |
564 | # On Python 2, importing pkg_resources tends to result in some 'ImportWarning' | |
565 | # being printed to stderr about packages missing __init__.py; the -W ignore is... | |
566 | # ignored. | |
3c6d899b | 567 | @@ -410,7 +416,7 @@ class ThreadTests(unittest.TestCase): |
5a03dc88 JB |
568 | self.should_raise = should_raise |
569 | self.thread = threading.Thread(target=self._run, | |
570 | args=(self,), | |
571 | - kwargs={'yet_another': self}) | |
572 | + kwargs={'_yet_another': self}) | |
573 | self.thread.start() | |
574 | ||
575 | def _run(self, _other_ref, _yet_another): | |
3c6d899b | 576 | @@ -463,7 +469,7 @@ class ThreadJoinOnShutdown(unittest.Test |
5a03dc88 JB |
577 | t = threading.Thread(target=joiningfunc, |
578 | args=(threading.current_thread(),)) | |
579 | t.start() | |
580 | - time.sleep(0.1) | |
581 | + time.sleep(0.2) | |
582 | print('end of main') | |
583 | """ | |
584 | self._run_and_join(script) | |
3c6d899b AM |
585 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/thread.py gevent-1.4.0/src/gevent/thread.py |
586 | --- gevent-1.4.0.org/src/gevent/thread.py 2019-01-04 12:51:44.000000000 +0100 | |
587 | +++ gevent-1.4.0/src/gevent/thread.py 2021-03-05 09:44:15.302384451 +0100 | |
588 | @@ -31,6 +31,8 @@ else: | |
589 | 'exit_thread', | |
590 | 'interrupt_main', | |
591 | 'start_new'] | |
592 | + if sys.version_info[:2] >= (3, 8): | |
593 | + __imports__.append('get_native_id') | |
594 | error = __thread__.error | |
595 | from gevent._compat import PY3 | |
596 | from gevent._compat import PYPY | |
597 | diff -urNp -x '*.orig' gevent-1.4.0.org/src/gevent/threading.py gevent-1.4.0/src/gevent/threading.py | |
598 | --- gevent-1.4.0.org/src/gevent/threading.py 2019-01-04 12:51:44.000000000 +0100 | |
599 | +++ gevent-1.4.0/src/gevent/threading.py 2021-03-05 09:44:15.299051013 +0100 | |
600 | @@ -156,41 +156,25 @@ import sys | |
601 | if sys.version_info[:2] >= (3, 4): | |
602 | # XXX: Issue 18808 breaks us on Python 3.4. | |
5a03dc88 JB |
603 | # Thread objects now expect a callback from the interpreter itself |
604 | - # (threadmodule.c:release_sentinel). Because this never happens | |
605 | + # (threadmodule.c:release_sentinel) when the C-level PyThreadState | |
606 | + # object is being deallocated. Because this never happens | |
607 | # when a greenlet exits, join() and friends will block forever. | |
608 | - # The solution below involves capturing the greenlet when it is | |
609 | - # started and deferring the known broken methods to it. | |
610 | + # Fortunately this is easy to fix: just ensure that the allocation of the | |
611 | + # lock, _set_sentinel, creates a *gevent* lock, and release it when | |
612 | + # we're done. The main _shutdown code is in Python and deals with | |
613 | + # this gracefully. | |
614 | ||
615 | class Thread(__threading__.Thread): | |
616 | - _greenlet = None | |
617 | - | |
618 | - def is_alive(self): | |
619 | - return bool(self._greenlet) | |
620 | - | |
621 | - isAlive = is_alive | |
622 | ||
623 | def _set_tstate_lock(self): | |
624 | - self._greenlet = getcurrent() | |
625 | - | |
626 | - def run(self): | |
627 | - try: | |
628 | - super(Thread, self).run() | |
629 | - finally: | |
630 | - # avoid ref cycles, but keep in __dict__ so we can | |
631 | - # distinguish the started/never-started case | |
632 | - self._greenlet = None | |
633 | - self._stop() # mark as finished | |
634 | - | |
635 | - def join(self, timeout=None): | |
636 | - if '_greenlet' not in self.__dict__: | |
637 | - raise RuntimeError("Cannot join an inactive thread") | |
638 | - if self._greenlet is None: | |
639 | - return | |
640 | - self._greenlet.join(timeout=timeout) | |
641 | - | |
642 | - def _wait_for_tstate_lock(self, *args, **kwargs): | |
643 | - # pylint:disable=arguments-differ | |
644 | - raise NotImplementedError() | |
645 | + super(Thread, self)._set_tstate_lock() | |
646 | + greenlet = getcurrent() | |
647 | + greenlet.rawlink(self.__greenlet_finished) | |
648 | + | |
649 | + def __greenlet_finished(self, _): | |
650 | + if self._tstate_lock: | |
651 | + self._tstate_lock.release() | |
652 | + self._stop() | |
653 | ||
654 | __implements__.append('Thread') | |
655 | ||
3c6d899b | 656 | @@ -199,6 +183,8 @@ if sys.version_info[:2] >= (3, 4): |
5a03dc88 JB |
657 | |
658 | __implements__.append('Timer') | |
659 | ||
660 | + _set_sentinel = allocate_lock | |
661 | + __implements__.append('_set_sentinel') | |
662 | # The main thread is patched up with more care | |
663 | # in _gevent_will_monkey_patch | |
664 |