Rust / rocket pass 변수를 엔드 포인트로 전달

Sep 06 2020

내 선호는 아니지만 오늘 Rust를 작성해야하므로 엔드 포인트가 하나만있는 Rocket 인스턴스를 만들려고하지만 해당 엔드 포인트에서 메인 중에 생성되는 변수에 액세스해야합니다. 변수를 인스턴스화하는 데 시간이 오래 걸리기 때문에 여기서 수행합니다.

제 문제는 안전하게 통과 할 방법을 찾을 수 없다는 것입니다. 내가 무엇을하든 컴파일러는 라이브러리가 스레드로부터 안전한 것처럼 보이지만 스레드 안전성에 대해 불평합니다.https://github.com/brave/adblock-rust/pull/130 (커밋 된 코드가 내 로컬 인스턴스에 있음)

이것은 내가 얻는 오류입니다.

   |
18 | / lazy_static! {
19 | |     static ref rules_engine: Mutex<Vec<Engine>> = Mutex::new(vec![]);
20 | | }
   | |_^ `std::rc::Rc<std::cell::RefCell<lifeguard::CappedCollection<std::vec::Vec<u64>>>>` cannot be sent between threads safely
   | 

... 그리고 이것은 내 코드입니다.

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use]
extern crate rocket;

use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;

use lazy_static::lazy_static;
use std::sync::Mutex;

use adblock::engine::Engine;
use adblock::lists::FilterFormat;

use rocket::request::{Form, FormError, FormDataError};

lazy_static! {
    static ref rules_engine: Mutex<Vec<Engine>> = Mutex::new(vec![]);
}

fn main() {
    if !Path::new("./rules.txt").exists() {
        println!("rules file does not exist")
    } else {
        println!("loading rules");

        let mut rules = vec![];

        if let Ok(lines) = read_lines("./rules.txt") {
            for line in lines {
                if let Ok(ip) = line {
                    rules.insert(0, ip)
                }
            }

            let eng = Engine::from_rules(&rules, FilterFormat::Standard);
            rules_engine.lock().unwrap().push(eng);
            rocket().launch();
        }
    }
}

#[derive(Debug, FromForm)]
struct FormInput<> {
    #[form(field = "textarea")]
    text_area: String
}

#[post("/", data = "<sink>")]
fn sink(sink: Result<Form<FormInput>, FormError>) -> String {
    match sink {
        Ok(form) => {
            format!("{:?}", &*form)
        }
        Err(FormDataError::Io(_)) => format!("Form input was invalid UTF-8."),
        Err(FormDataError::Malformed(f)) | Err(FormDataError::Parse(_, f)) => {
            format!("Invalid form input: {}", f)
        }
    }
}

fn rocket() -> rocket::Rocket {
    rocket::ignite().mount("/", routes![sink])
}

fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
    where P: AsRef<Path>, {
    let file = File::open(filename)?;
    Ok(io::BufReader::new(file).lines())
}

데 어떤 방법 eng내에서 사용할 수를 sink엔드 포인트 방법은?

답변

2 kmdreko Sep 06 2020 at 10:55

Rc뮤텍스 뒤에서도 스레드로부터 안전하지 않습니다. 그것은 모양 Rc에 사용되는 eng.blocker.pool.pool이다 lifeguard::Pool. 따라서은 Engine스레드로부터 안전하지 않습니다 (적어도 기본적으로).

다행히 adblock 크레이트에는 특정 기능을 활성화하는 "개체 풀링"이라는 기능 이있는 것으로 보입니다 . 해당 기능을 제거하면 스레드가 안전 해집니다.