Skip to content

Commit

Permalink
Merge pull request #63 from heuer/issue_61_listener_signal_ref
Browse files Browse the repository at this point in the history
Listener removes itself from Signal._link
  • Loading branch information
flacjacket authored Jul 26, 2024
2 parents 94cdb6e + e1daa71 commit 17b5cd2
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
1 change: 1 addition & 0 deletions pywayland/ffi_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
struct wl_list listener_list;
};
void wl_signal_init(struct wl_signal *signal);
void wl_signal_add(struct wl_signal *signal, struct wl_listener *listener);
void wl_signal_emit(struct wl_signal *signal, void *data);
"""
Expand Down
11 changes: 9 additions & 2 deletions pywayland/server/listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,16 @@ def __init__(self, function: Callable) -> None:
self._signal = None

def remove(self) -> None:
"""Remove the listener"""
"""Remove the listener.
After removal the listener must not be used anymore.
"""
if self._ptr and self._ptr.link != ffi.NULL:
lib.wl_list_remove(ffi.addressof(self._ptr.link))
assert self._signal
self._signal._link.remove(self)
self._signal = None
self._notify = None
self._ptr = None


Expand All @@ -95,7 +102,7 @@ class Signal:

def __init__(self, *, ptr=None, data_wrapper=None):
if ptr is None:
self._ptr = ffi.new("struct wl_listener *")
self._ptr = ffi.new("struct wl_signal *")
lib.wl_signal_init(self._ptr)
else:
self._ptr = ptr
Expand Down
32 changes: 32 additions & 0 deletions test/test_issue_61.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""
Test against issue <https://github.com/flacjacket/pywayland/issues/61>
"""

from pywayland.server import Listener, Signal


def test_ref_removal():

def callback(*_):
pass

sig = Signal()
listener = Listener(callback)
assert listener._ptr is not None
assert listener._notify is not None
assert listener._signal is None
assert not sig._link
sig.add(listener)
assert len(sig._link) == 1
assert listener._signal == sig
listener.remove()
assert len(sig._link) == 0
assert listener._signal is None
assert listener._notify is None
assert listener._ptr is None


if __name__ == "__main__":
import pytest

pytest.main([__file__])

0 comments on commit 17b5cd2

Please # to comment.