我是CapnProto的新手。
我想在server2的回调中请求一个server1函数。
但我有例外情况如下。
请帮我解决这个问题。
非常感谢!
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x3000000000020)
* frame #0: 0x000000010035859c libcapnp-rpc-0.10.2.dylib`capnp::VatNetwork<capnp::rpc::twoparty::VatId, capnp::rpc::twoparty::ProvisionId, capnp::rpc::twoparty::RecipientId, capnp::rpc::twoparty::ThirdPartyCapId, capnp::rpc::twoparty::JoinResult>::baseConnect(capnp::AnyStruct::Reader) + 20
frame #1: 0x0000000100361a2c libcapnp-rpc-0.10.2.dylib`kj::_::TransformPromiseNode<kj::_::Void, kj::Own<kj::AsyncIoStream>, capnp::EzRpcClient::Impl::Impl(kj::StringPtr, unsigned int, capnp::ReaderOptions)::'lambda'(kj::Own<kj::AsyncIoStream>&&), kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue&) + 512
frame #2: 0x00000001004d2220 libkj-async-0.10.2.dylib`kj::_::RunnableImpl<kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue&)::$_31>::run() + 32
frame #3: 0x000000010028aaa4 libkj-0.10.2.dylib`kj::_::runCatchingExceptions(kj::_::Runnable&) + 40
frame #4: 0x00000001004c7e48 libkj-async-0.10.2.dylib`kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue&) + 64
frame #5: 0x00000001004c8684 libkj-async-0.10.2.dylib`kj::_::ForkHubBase::fire() + 60
frame #6: 0x00000001004c654c libkj-async-0.10.2.dylib`kj::_::waitImpl(kj::Own<kj::_::PromiseNode>&&, kj::_::ExceptionOrValue&, kj::WaitScope&, kj::SourceLocation) + 608
frame #7: 0x0000000100005198 client`kj::Promise<capnp::Response<SampleServer1::CallbackRegisterResults> >::wait(kj::WaitScope&, kj::SourceLocation) + 120
frame #8: 0x0000000100004b94 client`main + 344
frame #9: 0x000000010003d08c dyld`start + 520源代码实现示例如下所示:
SampleServer1.capnp:
interface SampleServer1 {
callbackRegister @0 (callback :Callback) -> (); //to register a callback
interface Callback {
calbackFunc @0 (in :Int32) -> ();
}
}SampleServer1 1::Server:
class SampleServer1Impl : public SampleServer1::Server
{
::kj::Promise<void> callbackRegister(CallbackRegisterContext context){
auto cb = context.getParams().getCallback());
auto request = cb.calbackFuncRequest(); //Call callback function
request.setIn(111);
auto promise = request.send();
return kj::READY_NOW;
}
}SampleServer1::Callback::Server Impl:
class CallbackImpl : public SampleServer1::Callback::Server
{
::kj::Promise<void> calbackFunc(CalbackFuncContext context){
capnp::EzRpcClient ezClient2("unix:/tmp/capnp-server-2");
SampleServer2::Client client2 = ezClient2.getMain<SampleServer2>();
auto& waitScope = ezClient2.getWaitScope();
{
auto request = client2.functionSampleRequest(); //Request to SERVER2
request.setIn(222);
auto promise = request.send();
promise.wait(waitScope);
}
return kj::READY_NOW;
}
}SampleServer2.capnp:
interface SampleServer2 {
functionSample @0 (in :Int32) -> ();
}SampleServer2 2::Server
class SampleServer2 Impl : public SampleServer2::Server
{
::kj::Promise<void> functionSample(FunctionSampleContext context){
//Do something
return kj::READY_NOW;
}
}客户端实现
capnp::EzRpcClient ezClient("unix:/tmp/capnp-server-1");
SampleServer1::Client client = ezClient.getMain<SampleServer1>();
auto& waitScope = ezClient.getWaitScope();
::SampleServer1::Callback::Client callback = ::SampleServer1::Callback::Client(kj::heap<CallbackImpl>());
auto request = client.callbackRegisterRequest(); //Register a callback to Server1
request.setCallback(callback);
auto promise = request.send();发布于 2022-09-12 07:02:00
calbackFunc的实现存在一个问题。calbackFunc本身是从NEVER_DONE.wait (事件循环)执行的,因此在此函数中等待承诺将导致嵌套等待。这在卡本普是不允许的。
您可以通过在另一个线程上这样做来避免这种情况。例如:
::kj::Promise<void> calbackFunc(CalbackFuncContext context){
kj::Thread th([](){
capnp::EzRpcClient ezClient2("unix:/tmp/capnp-server-2");
Server2::Client client2 = ezClient2.getMain<SampleServer2>();
auto& waitScope = ezClient2.getWaitScope();
{
auto request = client2.functionSampleRequest(); //Request to SERVER2
request.setIn(222);
auto promise = request.send();
promise.wait(waitScope);
}
});
return kj::READY_NOW;
}发布于 2022-10-02 22:35:56
与肯顿在另一个答复中的意见相似,以下几点对我来说是可行的:
::kj::Promise<void> calbackFunc(CalbackFuncContext context){
auto ezClient2 = kj::heap<capnp::EzRpcClient>("unix:/tmp/capnp-server-2");
SampleServer2::Client client2 = ezClient2->getMain<SampleServer2>();
auto request = client2.functionSampleRequest(); //Request to SERVER2
request.setIn(222);
return request.send().attach(kj::mv(ezClient2)).ignoreResult();备注:
request.send()生成的承诺,而不是像您使用kj::READY_NOW那样创建新的承诺。.attach ezClient2,因此它保持在request.send()承诺的范围内。自己试试:删除.attach()并看到它崩溃。阅读附件在这里的KJ之旅。.ignoreResult(),只是为了将request.send()承诺转换为kj::Promise<void>。它仍将正常完成,但它只是方便地将类型转换为我们可以从calbackFunc返回的内容。现在,假设您想在对functionSample()的请求完成后执行一些操作。您可以使用.then注册一个回调,以便在完成时调用(请参阅这里的文件):
::kj::Promise<void> calbackFunc(CalbackFuncContext context){
auto ezClient2 = kj::heap<capnp::EzRpcClient>("unix:/tmp/capnp-server-2");
SampleServer2::Client client2 = ezClient2->getMain<SampleServer2>();
auto request = client2.functionSampleRequest(); //Request to SERVER2
request.setIn(222);
return request.send().ignoreResult()
.then([]() {
// DO SOMETHING IN THE CONTINUATION HERE
}).attach(kj::mv(ezClient2));
}https://stackoverflow.com/questions/73681340
复制相似问题