Borrowed value does not live long enough with a Tokio future

∥☆過路亽.° 提交于 2021-01-29 12:53:30

问题


I'm trying to write a simple HTTP server using Rust and tokio.

Everything works fine until I want to send the response.

The code is the following:

use std::fs;
use std::sync::Arc;
use tokio::net::TcpListener; // 0.1.15
use tokio::prelude::*;

fn main() {
    let addr = "0.0.0.0:8080".parse().unwrap();
    let listener = TcpListener::bind(&addr).expect("unable to bind TCP listener");

    let incoming = listener.incoming();

    let server = incoming
        .map_err(|e| eprintln!("accept failed = {:?}", e))
        .for_each(|socket| {
            println!(
                "Connection established: from {:?} to {:?}",
                socket.peer_addr(),
                socket.local_addr()
            );
            let bytes = vec![0; 512];
            let processor = tokio::io::read(socket, bytes)
                .and_then(|(socket, bytes, _size)| {
                    println!("Request: {}", String::from_utf8_lossy(&bytes[..]));
                    let contents = fs::read_to_string("hello.html").unwrap();
                    let response = Arc::new(format!("HTTP/1.1 200 OK\r\n\r\n{}", contents));
                    let response = response.clone();
                    tokio::io::write_all(socket, response.as_bytes()).and_then(|_| Ok(()))
                })
                .map_err(|_| ());
            tokio::spawn(processor);
            Ok(())
        });

    tokio::run(server);
}
error[E0597]: `response` does not live long enough
  --> src/main.rs:27:50
   |
27 |                     tokio::io::write_all(socket, response.as_bytes()).and_then(|_| Ok(()))
   |                                                  ^^^^^^^^ borrowed value does not live long enough
28 |                 })
   |                 - `response` dropped here while still borrowed

How do I have to declare the response to live enough?


回答1:


How can you make it work ?

As i pointed in my comment: use into_bytes, instead of wrapping with Arc and passing the borrowed bytes array.

Playground


@David:

But I don't understand why wrapping with arc didn't.

Arc counts reference of inner object:

  • it increases the reference when you clone()
  • it decreases the reference when the owner of Arc gets dropped.
  • it gets dropped from the memory when reference count decreases to 0

In your case owner of the Arc, which is named as response. response is created in scope and dropped at the end of the same scope. It's ref count was 1 when it was created, it became 0 after dropped. But you've passed a reference of Arc inside a Future right before it has removed from memory.

Please note that write_all() creates a Future and that Future carries a reference of your Arc, which is removed from memory before the Future's execution.

Note: WriteAll can have ownership of borrowed or moved value it expects a generic parameter which can be converted to a slice.



来源:https://stackoverflow.com/questions/55610608/borrowed-value-does-not-live-long-enough-with-a-tokio-future

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!