Skip to content

Commit

Permalink
Fix segfault in on_disconnect
Browse files Browse the repository at this point in the history
  • Loading branch information
LasseBlaauwbroek committed Jun 12, 2023
1 parent 5b9fb19 commit 7f745f7
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
4 changes: 4 additions & 0 deletions capnp/lib/capnp.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2247,6 +2247,8 @@ cdef class TwoPartyClient:
return _CapabilityClient()._init(helpers.bootstrapHelper(deref(self.thisptr)), self)

cpdef on_disconnect(self) except +reraise_kj_exception:
if self.closed:
raise RuntimeError("This client is closed")
return self._network.on_disconnect()


Expand Down Expand Up @@ -2300,6 +2302,8 @@ cdef class TwoPartyServer:
return _CapabilityClient()._init(helpers.bootstrapHelperServer(deref(self.thisptr)), self)

cpdef on_disconnect(self) except +reraise_kj_exception:
if self.closed:
raise RuntimeError("This server is closed")
return _voidpromise_to_asyncio(deref(self._network.thisptr).onDisconnect()
.attach(capnp.heap[PyRefCounter](<PyObject*>self)))

Expand Down
35 changes: 34 additions & 1 deletion test/test_context_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,31 @@ async def test_kj_loop_partial_write_message_after_close():
assert "The KJ event-loop is not running" in str(exninfo)


async def test_client_on_disconnect_memory():
read, _ = socket.socketpair()
async with capnp.kj_loop():
read = await capnp.AsyncIoStream.create_connection(sock=read)
client = capnp.TwoPartyClient(read)
with pytest.raises(RuntimeError) as exninfo:
await client.on_disconnect()
assert "This client is closed" in str(exninfo)


async def test_server_on_disconnect_memory():
_, write = socket.socketpair()
async with capnp.kj_loop():
write = await capnp.AsyncIoStream.create_connection(sock=write)
server = capnp.TwoPartyServer(write, bootstrap=test_capability.Server())
with pytest.raises(RuntimeError) as exninfo:
await server.on_disconnect()
assert "This server is closed" in str(exninfo)


@pytest.mark.xfail(
strict=True,
reason="Fails because the promisefulfiller got destroyed. Possibly a bug in the C++ library.",
)
async def test_client_on_disconnect_memory():
async def test_client_on_disconnect_memory2():
"""
E capnp.lib.capnp.KjException: kj/async.c++:2813: failed:
PromiseFulfiller was destroyed without fulfilling the promise.
Expand All @@ -210,3 +230,16 @@ async def test_client_on_disconnect_memory():
client = capnp.TwoPartyClient(read)
disc = client.on_disconnect()
await disc


async def test_server_on_disconnect_memory2():
"""
E capnp.lib.capnp.KjException: kj/async.c++:2813: failed:
PromiseFulfiller was destroyed without fulfilling the promise.
"""
_, write = socket.socketpair()
async with capnp.kj_loop():
write = await capnp.AsyncIoStream.create_connection(sock=write)
server = capnp.TwoPartyServer(write, bootstrap=test_capability.Server())
disc = server.on_disconnect()
await disc

0 comments on commit 7f745f7

Please sign in to comment.