Skip to content

Commit

Permalink
Experiment: Wrap all capnp code in a context-manager to avoid segfaul…
Browse files Browse the repository at this point in the history
…ts (#317)

* Experiment: Wrap all capnp code in a context-manager

* Fix segfault in on_disconnect
  • Loading branch information
LasseBlaauwbroek authored Oct 3, 2023
1 parent d48ffea commit e13a0c9
Show file tree
Hide file tree
Showing 23 changed files with 525 additions and 140 deletions.
8 changes: 6 additions & 2 deletions capnp/helpers/capabilityHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,14 @@ ::kj::Promise<kj::Own<PyRefCounter>> then(kj::Promise<kj::Own<PyRefCounter>> pro
}

kj::Promise<void> PythonInterfaceDynamicImpl::call(capnp::InterfaceSchema::Method method,
capnp::CallContext< capnp::DynamicStruct, capnp::DynamicStruct> context) {
capnp::CallContext< capnp::DynamicStruct,
capnp::DynamicStruct> context) {
auto methodName = method.getProto().getName();

kj::Promise<void> * promise = call_server_method(py_server, const_cast<char *>(methodName.cStr()), context);
kj::Promise<void> * promise = call_server_method(this->py_server->obj,
const_cast<char *>(methodName.cStr()),
context,
this->kj_loop->obj);

check_py_error();

Expand Down
14 changes: 6 additions & 8 deletions capnp/helpers/capabilityHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,15 @@ ::kj::Promise<kj::Own<PyRefCounter>> then(kj::Promise<kj::Own<PyRefCounter>> pro

class PythonInterfaceDynamicImpl final: public capnp::DynamicCapability::Server {
public:
PyObject * py_server;
kj::Own<PyRefCounter> py_server;
kj::Own<PyRefCounter> kj_loop;

PythonInterfaceDynamicImpl(capnp::InterfaceSchema & schema, PyObject * _py_server)
: capnp::DynamicCapability::Server(schema), py_server(_py_server) {
GILAcquire gil;
Py_INCREF(_py_server);
}
PythonInterfaceDynamicImpl(capnp::InterfaceSchema & schema,
kj::Own<PyRefCounter> _py_server,
kj::Own<PyRefCounter> kj_loop)
: capnp::DynamicCapability::Server(schema), py_server(kj::mv(_py_server)), kj_loop(kj::mv(kj_loop)) { }

~PythonInterfaceDynamicImpl() {
GILAcquire gil;
Py_DECREF(py_server);
}

kj::Promise<void> call(capnp::InterfaceSchema::Method method,
Expand Down
2 changes: 1 addition & 1 deletion capnp/includes/capnp_cpp.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ cdef extern from "capnp/helpers/capabilityHelper.h":
Exception makeException(StringPtr message)
PyPromise tryReadMessage(AsyncIoStream& stream, ReaderOptions opts)
cppclass PythonInterfaceDynamicImpl:
PythonInterfaceDynamicImpl(InterfaceSchema&, PyObject *)
PythonInterfaceDynamicImpl(InterfaceSchema&, Own[PyRefCounter] server, Own[PyRefCounter] kj_loop)

cdef extern from "capnp/serialize-async.h" namespace " ::capnp":
VoidPromise writeMessage(AsyncIoStream& output, MessageBuilder& builder)
2 changes: 1 addition & 1 deletion capnp/lib/capnp.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ cdef _setDynamicFieldStatic(DynamicStruct_Builder thisptr, field, value, parent)

cdef api object wrap_dynamic_struct_reader(Response & r) with gil
cdef api Promise[void] * call_server_method(
object server, char * _method_name, CallContext & _context) except * with gil
object server, char * _method_name, CallContext & _context, object kj_loop) except * with gil
cdef api object wrap_kj_exception(capnp.Exception & exception) with gil
cdef api object wrap_kj_exception_for_reraise(capnp.Exception & exception) with gil
cdef api object get_exception_info(object exc_type, object exc_obj, object exc_tb) with gil
Loading

0 comments on commit e13a0c9

Please sign in to comment.