Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • pypy pypy
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 677
    • Issues 677
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 13
    • Merge requests 13
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Container Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • PyPyPyPy
  • pypypypy
  • Issues
  • #3381
Closed
Open
Issue created Jan 12, 2021 by Jason Madden@jamadden

greenlet.error not raised switching between threads for main greenlet

Consider this code snippet. It starts a background thread and exposes an attribute that allows switching to the main greenlet of the background thread. The main thread then attempts to call this switch method.

# bad_switch.py
from time import sleep as native_sleep
from threading import Thread as NativeThread
from threading import Event as NativeEvent

import greenlet


class Thread(NativeThread):
    def __init__(self):
        NativeThread.__init__(self)
        self.switch_to_greenlet = None
        self.running = NativeEvent()
        self.daemon = True

    def run(self):
        self.switch_to_greenlet = greenlet.getcurrent().switch
        def bg():
            self.running.set()
            native_sleep(10)

        glet = greenlet.greenlet(bg)
        glet.switch()
        print('T2: Resumed')


t = Thread()
t.start()
t.running.wait()
t.switch_to_greenlet() # line 29

Under CPython with any version of greenlet, this results in the main thread raising an exception:

$ python bad_switch.py
Traceback (most recent call last):
  File "/private/tmp/bad_switch.py", line 29, in <module>
    t.switch_to_greenlet()
greenlet.error: cannot switch to a different thread

Under PyPy, however, nothing appears to happen. The main thread raises no exception, but neither is the greenlet resumed ("T2: Resumed" is not printed). I've tested this with PyPy 2.7-7.3.3 (macOS and Linux), PyPy 3.7-7.3.3 (mac only) and pypy-c-jit-101407-060e8d505b33-osx64.

The same thing happens if the bg greenlet is deleted and the background thread runs all the code itself in the main greenlet.

PyPy does raise the expected error if you attempt to switch to a non-main greenlet in a different thread; defining run like so:

    def run(self):

        run_main = greenlet.getcurrent().switch
        def bg():
            print("T2G2: running; switching to main")
            run_main()
            print("t2g2: resumed")
            native_sleep(10)

        glet = greenlet.greenlet(bg)
        self.switch_to_greenlet = glet.switch
        glet.switch()
        print('T2G1: Resumed')
        self.running.set()
        native_sleep(10)

results in:

$ pypy3 bad_switch.py
T2G2: running; switching to main
T2G1: Resumed
Traceback (most recent call last):
  File "bad_switch.py", line 35, in <module>
    t.switch_to_greenlet()
  File "//pypy3/lib_pypy/greenlet.py", line 54, in switch
    return self.__switch('switch', (args, kwds))
  File "//pypy3/lib_pypy/greenlet.py", line 93, in __switch
    args, kwds = unbound_method(current, *baseargs, to=target)
_continuation.error: inter-thread support is missing

This comes up in the context of gevent, where I've had a bug report that switching between different threads like in the first example just hangs. On CPython, this was a bug where gevent was silently catching and ignoring the greenlet.error but on PyPy, because there's no error and nothing seems to happen when you switch(), I don't know how to fix, or even detect, the hang.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking