rust 使用select退出线程

发布于:2025-04-08 ⋅ 阅读:(30) ⋅ 点赞:(0)
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct Capture {
    clear: bool,       // ????????
    interface: String, // ??
    times: u64,        // ??
}

pub async fn cmd_capture(
    State(web_env): State<ArcWebEnv>,
    Json(args): Json<Capture>,
) -> Result<impl IntoResponse, WebError> {
    let env = web_env.env.lock().await;
    let mac = env.conf.mac.clone().split(':').collect::<Vec<&str>>().join("");
    let capture_status = env.capture_status.clone(); // shiyong suo
    {
        let mut cs = capture_status.lock().await;
        info!("current upload status  ={}", cs.uploading);
        if args.clear && cs.uploading {
            cs.sender
                .try_send(())
                .map_err(|e| {
                    warn!("Failed to send stop signal: {:?}", e);
                    e
                })
                .ok();
            return Err(WebError::new(StatusCode::ACCEPTED, anyhow!("capture task has been cleared")));
        }
        if !args.clear && cs.uploading {
            return Err(WebError::new(StatusCode::ACCEPTED, anyhow!("capture task is currently in progress. ignore")));
        }

        if args.clear && !cs.uploading {
            return Err(WebError::new(StatusCode::ACCEPTED, anyhow!("capture task is not exist. ignore")));
        }
        let stop_rx = cs.rec.take().ok_or_else(|| {
            WebError::new(StatusCode::ACCEPTED, anyhow!("capture task is currently in progressing. ignore"))
        })?;
        let capture_status_for_task = capture_status.clone();
        let capture_task = start_capture_thread(capture_status_for_task, args.clone(), stop_rx, mac);
        capture_task.await?;
    }
    Ok(())
}

注意一点: 

不能删除take 这行代码。这行代码的作用是从 cs.rec(类型为 Option<mpsc::Receiver<()>>)中取出停止信号的接收端,并传递给 start_capture_thread。由于 mpsc::Receiver 本身不可克隆,所以我们需要调用 .take() 将它的所有权转移出去。如果删除这行代码,就无法获取到 stop_rx,也就失去了停止抓包任务的机制。