Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: issue with callbacks that also call proxy methods: #4

Open
tlambert03 opened this issue Nov 5, 2024 · 3 comments
Open

Bug: issue with callbacks that also call proxy methods: #4

tlambert03 opened this issue Nov 5, 2024 · 3 comments

Comments

@tlambert03
Copy link
Member

something is broken when a signal callback connected to a proxy event itself calls proxy methods:

def test_cb(proxy: CMMCorePlus) -> None:
    mock = Mock()

    @proxy.events.imageSnapped.connect
    def callback() -> None:
        proxy.getLoadedDevices()  # test fails unless you comment out this line
        mock()

    proxy.snapImage()
    mock.assert_called_once()
@tlambert03
Copy link
Member Author

https://pyro5.readthedocs.io/en/latest/clientcode.html#proxy-sharing-between-threads

and

https://github.com/irmen/Pyro5/blob/master/examples/threadproxysharing/client.py#L14

however... if I use _pyroClaimOwnership, I deadlock, because we're doing exactly what they discourage doing (circular communication) in the tips and tricks

@tlambert03
Copy link
Member Author

it's going to be extremely hard to support the use case as posed in the original post here.

if I try to use _pyroClaimOwnership on a single proxy object, inside of the callback, then I get deadlocks (that can also be explored).

One solution is to have the callback itself create an independent proxy to the same URI... but if we want the end-user (e.g. napari-micromanager or other users of pymmcore-remote) to be able to call core methods within callbacks as if they weren't using the proxy at all (which we kind of do), then the only solution I can currently think of is some rather dark magic of mucking with the locals() and closures of the callback (swapping in a new proxy object) before calling the callback... and that would require deep mucking with psygnal itself, and is probably incompatible with Qt.

@tlambert03
Copy link
Member Author

this works:

def test_cb_with_core_method(proxy: CMMCorePlus) -> None:
    mock = Mock()
    from psygnal import emit_queued

    @proxy.events.imageSnapped.connect(thread="main")
    def callback() -> None:
        d = proxy.getLoadedDevices()  # test fails unless you comment out this line
        mock()

    proxy.snapImage()
    emit_queued()
    mock.assert_called_once()

see psygnal docs: https://psygnal.readthedocs.io/en/latest/usage/#connecting-across-threads

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant