Lifetime issue with EventLoop
Closed this issue · 3 comments
Having a hard time figuring out a solution to this lifetime problem. Essentially I have a worker thread for registering mdns entries, each of which requires an MdnsService and an EventLoop. Somehow creating the EventLoop is holding a mutable borrow to the MdnsService and I can't quite figure out how to handle the lifetimes. My code is:
pub struct ServiceData<'a> {
pub service: AvahiMdnsService,
pub event_loop: AvahiEventLoop<'a>,
}
fn service_registration_thread(rx_channel: Receiver<ChannelCommand>) {
let mut services: Vec<ServiceData> = Vec::new();
loop {
for message in rx_channel.try_iter() {
match message {
ChannelCommand::NewService(service_ref) => {
let mut txt_data = TxtRecord::new();
for item in service_ref.txt_records.iter() {
txt_data.insert(item.0, item.1).unwrap();
}
let service_type = ServiceType::new(
&service_ref.service_name.to_owned(),
&service_ref.protocol.to_owned(),
)
.unwrap();
136: let mut new_service = MdnsService::new(service_type, service_ref.port);
new_service.set_name(&service_ref.instance_name.to_owned());
new_service.set_txt_record(txt_data);
new_service
.set_registered_callback(Box::new(MDnsService::on_service_registered));
141: let event_loop = [new_service.register](https://github.com/windy1/zeroconf-rs/blob/850c028aa8e85fb3ee441b344e2dbecb8d7f9a0c/zeroconf/src/linux/service.rs#L109C1-L129)().unwrap();
let data = ServiceData {
service: new_service,
145: event_loop: event_loop,
};
services.push(data)
}
}
}
for service in services.iter() {
service.event_loop.poll(Duration::from_millis(0));
}
}
}
I get the error:
cannot move out of `new_service` because it is borrowed
move out of `new_service` occurs here:
async_service.rs(141, 42): borrow of `new_service` occurs here
async_service.rs(136, 29): binding `new_service` declared here
async_service.rs(145, 41): borrow later used here
It seems to have something to do with how PhantomData in AvahiEventLoop is capturing the mutable borrow, but can't quite tell if there's a way to handle this in my code or if the library really needs to change. I've tried various permutations of Rc & RefCell around new_service but that doesn't seem to help with checking the ownership of that borrow on 141.
Yes, I believe that the PhantomData
is not working as intended. The original intent here was to prevent the service from being dropped before the EventLoop
, but I think this was a mistake. Admittedly, I was new to the language at the time and hadn't quite wrapped my head around lifetimes yet.
I have a branch (refactor/arc-rc) that I started a few weeks ago that should resolve this issue by removing the lifetime parameter entirely; instead managing the early-drop problem using Rc
s. I will try to wrap that work up soon™️.
I'll have to peak at that branch. The Rcs almost seemed to cause more problems than they solve. May make sense for the EventLoop to just take a reference to poll. When the service drops it just drops a whole bunch of stuff, like the client and context so just keeping poll alive isn't all that helpful.
This should be fixed in 0.14.0
, let me know if you have any issues. Also, just FYI, you should probably be using MdnsService
instead of AvahiMdnsService
and EventLoop
instead of AvahiEventLoop
.