Closed i509VCB closed 1 year ago
Inside of pre_run and post_run, registering an event source will cause a double borrow.
pre_run
post_run
This is also possible inside of the callback provided to insert_idle since registering an idle callback inside of an idle callback will double borrow.
insert_idle
I reproduced the double borrow with the following code:
use calloop::{ ping::PingSource, EventLoop, EventSource, LoopHandle, Poll, PostAction, Readiness, Token, TokenFactory, }; struct State { loop_handle: LoopHandle<'static, Self>, } #[test] fn insert_in_dispatch() { let mut event_loop = EventLoop::try_new().unwrap(); let handle = event_loop.handle(); let mut state = State { loop_handle: handle.clone(), }; let timer = OneshotRemove::new(); handle.insert_source(timer, handle_source).unwrap(); event_loop.run(None, &mut state, |_| {}).unwrap(); } fn handle_source(_: (), _: &mut (), state: &mut State) { state .loop_handle .insert_source(OneshotRemove::new(), handle_source) .unwrap(); } struct OneshotRemove { source: PingSource, } impl OneshotRemove { pub fn new() -> Self { let (ping, source) = calloop::ping::make_ping().unwrap(); let source = Self { source }; // Immediately ping the source to dispatch on register ping.ping(); source } } impl EventSource for OneshotRemove { type Event = (); type Metadata = (); type Ret = (); type Error = calloop::Error; fn pre_run<F>(&mut self, mut callback: F) -> calloop::Result<()> where F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, { callback((), &mut ()); Ok(()) } fn process_events<F>( &mut self, readiness: Readiness, token: Token, _callback: F, ) -> Result<PostAction, Self::Error> where F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, { self.source .process_events(readiness, token, |_, _| {}) .unwrap(); Ok(PostAction::Remove) } fn register( &mut self, poll: &mut Poll, token_factory: &mut TokenFactory, ) -> calloop::Result<()> { self.source.register(poll, token_factory) } fn reregister( &mut self, poll: &mut Poll, token_factory: &mut TokenFactory, ) -> calloop::Result<()> { self.source.reregister(poll, token_factory) } fn unregister(&mut self, poll: &mut Poll) -> calloop::Result<()> { self.source.unregister(poll) } }
The following backtrace is produced: https://gist.github.com/i509VCB/0b27d3a5eb57ae7594243cd5b4833cf7
Inside of
pre_run
andpost_run
, registering an event source will cause a double borrow.This is also possible inside of the callback provided to
insert_idle
since registering an idle callback inside of an idle callback will double borrow.I reproduced the double borrow with the following code:
The following backtrace is produced: https://gist.github.com/i509VCB/0b27d3a5eb57ae7594243cd5b4833cf7