Question about Tokio and shared state

Hi,

I'm confused about Tokio and shared state. Consider this code (note the use of &self. records within the loop):

pub struct DnsServer {
    port: u16,
    records: HashMap<String, Ipv4Addr>,
}

impl DnsServer {
    pub async fn new(port: u16) -> Result<Self> {
        let config = DotLocalDNSConfig::new().await?;
        Ok(Self {
            port,
            records: config.records,
        })
    }

    pub async fn run(&self) -> Result<()> {
        let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, self.port));
        let socket = mk_udp_socket(&addr).await?;
        println!("Listening on: localhost:{}", self.port);
        loop {
            let mut req_buffer = BytePacketBuffer::new();
            let (_len, peer) = socket.recv_from(&mut req_buffer.buf).await?;
            let request = DnsPacket::from_buffer(&mut req_buffer).await?;
            let mut response = lookup(&request, &self.records)?;
            let mut res_buffer = BytePacketBuffer::new();
            response.write(&mut res_buffer)?;
            let pos = res_buffer.pos();
            let data = res_buffer.get_range(0, pos)?;
            let _ = socket.send_to(data, peer).await?;
        }
    }
}

This works fine when I do some simple queries (even repeatedly) but I'm wondering If there is a scenario where the future will switch to another thread and then it'll break? What I'm asking is if I can always trust the compiler to be right about types in async/tokio environment?

If not, do I have to wrap every DnsServer field that is accessed from within the run loop with Arc or maybe only the ones I need to mutate with Arc<Mutex/RWLock>?

Thanks

I wouldn't worry if you don't do anything unsafe, like manually implement Send or Sync for a type that really isn't, or extending the lifetime of a reference to pretend it is 'static. I find it far more likely that you'll run into problems and deadlocks due to logic errors like faulty synchronisation or blocking the runtime.

1 Like

Thanks, does this mean I can trust the compiler (if I'm not doing any of the unsafe things you mentioned)?

Yes

1 Like