Skip to content

Commit e0d9705

Browse files
committed
Make cross-thread locks use native blocking and timeouts instead of spinning.
This may improve scenarios like #2013
1 parent 31ebe75 commit e0d9705

3 files changed

Lines changed: 22 additions & 19 deletions

File tree

.github/workflows/ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -517,11 +517,6 @@ jobs:
517517
GEVENT_MANYLINUX_NAME: ${{ matrix.image }}
518518

519519
run: scripts/releases/make-manylinux
520-
- name: Upload gevent wheels
521-
uses: actions/upload-artifact@v4
522-
with:
523-
path: wheelhouse/*whl
524-
name: ${{ matrix.config[2] }}_x86_64_wheels.zip
525520
- name: Publish package to PyPI
526521
uses: pypa/[email protected]
527522
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
@@ -530,6 +525,11 @@ jobs:
530525
password: ${{ secrets.TWINE_PASSWORD }}
531526
skip_existing: true
532527
packages_dir: wheelhouse/
528+
- name: Upload gevent wheels
529+
uses: actions/upload-artifact@v4
530+
with:
531+
path: wheelhouse/*whl
532+
name: ${{ matrix.image }}_wheels.zip
533533

534534
# TODO:
535535
# * Use YAML syntax to share snippets, like the old .travis.yml did

docs/changes/2020.bugfix

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,8 @@ Other changes:
1919
- Drop ``setuptools`` to a soft test dependency.
2020
- Drop support for very old versions of CFFI.
2121
- Update bundled c-ares from 1.19.1 to 1.26.0.
22+
- Locks created by gevent, but acquired from multiple different
23+
threads (not recommended), no longer spin to implement timeouts
24+
and interruptible blocking. Instead, they use the native
25+
functionality of the Python 3 lock. This may improve some scenarios.
26+
See :issue:`2013`

src/gevent/_semaphore.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ class Semaphore(AbstractLinkable): # pylint:disable=undefined-variable
7777
.. versionchanged:: 20.12.0
7878
Improved support for multi-threaded usage. When multi-threaded usage is detected,
7979
instances will no longer create the thread's hub if it's not present.
80+
81+
.. versionchanged:: NEXT
82+
Uses Python 3 native lock timeouts for cross-thread operations instead
83+
of spinning.
8084
"""
8185

8286
__slots__ = (
@@ -449,22 +453,16 @@ def __acquire_without_hubs(self, timeout):
449453
return False
450454

451455
def __spin_on_native_lock(self, thread_lock, timeout):
452-
expiration = 0
453-
if timeout:
454-
expiration = monotonic() + timeout
455-
456456
self._drop_lock_for_switch_out()
457457
try:
458-
# TODO: When timeout is given and the lock supports that
459-
# (Python 3), pass that.
460-
# Python 2 has terrible behaviour where lock acquires can't
461-
# be interrupted, so we use a spin loop
462-
while not thread_lock.acquire(0):
463-
if expiration and monotonic() >= expiration:
464-
return False
465-
466-
_native_sleep(0.001)
467-
return True
458+
# Unlike Python 2, Python 3 thread locks
459+
# can be interrupted when blocking, with or
460+
# without a timeout. Python 2 didn't even
461+
# support a timeout for non -blocking.
462+
if timeout:
463+
return thread_lock.acquire(True, timeout)
464+
465+
return thread_lock.acquire()
468466
finally:
469467
self._acquire_lock_for_switch_in()
470468

0 commit comments

Comments
 (0)