Skip to content

Commit f1656e5

Browse files
committed
handle case when RpcSystem.get_disconnector() is called before bootstrap()
1 parent 17a4bec commit f1656e5

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

capnp-rpc/src/rpc.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,7 @@ impl<VatId> ConnectionState<VatId> {
15881588
}
15891589

15901590
enum DisconnectorState {
1591-
Connected,
1591+
New,
15921592
Disconnecting,
15931593
Disconnected,
15941594
}
@@ -1604,13 +1604,9 @@ where
16041604

16051605
impl<VatId> Disconnector<VatId> {
16061606
pub fn new(connection_state: Rc<RefCell<Option<Rc<ConnectionState<VatId>>>>>) -> Self {
1607-
let state = match *(connection_state.borrow()) {
1608-
Some(_) => DisconnectorState::Connected,
1609-
None => DisconnectorState::Disconnected,
1610-
};
16111607
Self {
16121608
connection_state,
1613-
state,
1609+
state: DisconnectorState::New,
16141610
}
16151611
}
16161612
fn disconnect(&self) {
@@ -1630,7 +1626,7 @@ where
16301626

16311627
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
16321628
self.state = match self.state {
1633-
DisconnectorState::Connected => {
1629+
DisconnectorState::New => {
16341630
self.disconnect();
16351631
DisconnectorState::Disconnecting
16361632
}
@@ -1644,7 +1640,7 @@ where
16441640
DisconnectorState::Disconnected => DisconnectorState::Disconnected,
16451641
};
16461642
match self.state {
1647-
DisconnectorState::Connected => unreachable!(),
1643+
DisconnectorState::New => unreachable!(),
16481644
DisconnectorState::Disconnecting => {
16491645
cx.waker().wake_by_ref();
16501646
Poll::Pending

capnp-rpc/test/test.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,55 @@ fn disconnector_disconnects() {
186186
});
187187
}
188188

189+
#[test]
190+
fn disconnector_disconnects_2() {
191+
let mut pool = futures::executor::LocalPool::new();
192+
let mut spawner = pool.spawner();
193+
let (mut client_rpc_system, server_rpc_system) = disconnector_setup();
194+
195+
// Grab the disconnector before calling bootstrap().
196+
// At one point, this caused the disconnector to not work.
197+
let disconnector: capnp_rpc::Disconnector<capnp_rpc::rpc_twoparty_capnp::Side> =
198+
client_rpc_system.get_disconnector();
199+
200+
let client: test_capnp::bootstrap::Client =
201+
client_rpc_system.bootstrap(rpc_twoparty_capnp::Side::Server);
202+
203+
spawn(&mut spawner, client_rpc_system);
204+
205+
let (tx, rx) = oneshot::channel::<()>();
206+
207+
//send on tx when server_rpc_system exits
208+
spawn(
209+
&mut spawner,
210+
server_rpc_system.map(|x| {
211+
tx.send(()).expect("sending on tx");
212+
x
213+
}),
214+
);
215+
216+
pool.run_until(async move {
217+
//make sure we can make an RPC system call
218+
client
219+
.test_interface_request()
220+
.send()
221+
.promise
222+
.await
223+
.unwrap();
224+
225+
//disconnect from the server; comment this next line out to see the test fail
226+
disconnector.await.unwrap();
227+
228+
rx.await.expect("rpc system should exit");
229+
230+
//make sure we can't use client any more (because the server is disconnected)
231+
match client.test_interface_request().send().promise.await {
232+
Err(ref e) if e.kind == ::capnp::ErrorKind::Disconnected => (),
233+
_ => panic!("Should have gotten a 'disconnected' error."),
234+
}
235+
});
236+
}
237+
189238
fn rpc_top_level<F, G>(main: F)
190239
where
191240
F: FnOnce(futures::executor::LocalSpawner, test_capnp::bootstrap::Client) -> G,

0 commit comments

Comments
 (0)