From 5d93e38237202a2918362522be6097745a0233b2 Mon Sep 17 00:00:00 2001 From: shenjack-5600u <3695888@qq.com> Date: Mon, 7 Apr 2025 05:28:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=20Python=20?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E5=81=9C=E4=B8=8D=E4=B8=8B=E6=9D=A5=E5=B0=B1?= =?UTF-8?q?=E7=9C=9F=E7=9A=84=E5=81=9C=E4=B8=8D=E4=B8=8B=E6=9D=A5=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ica-rs/src/error.rs | 6 ++++++ ica-rs/src/main.rs | 20 ++++++++++++++++++-- ica-rs/src/py/mod.rs | 17 +++++++---------- news/0-9.md | 2 ++ 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/ica-rs/src/error.rs b/ica-rs/src/error.rs index 58051f4..e55d1e8 100644 --- a/ica-rs/src/error.rs +++ b/ica-rs/src/error.rs @@ -33,6 +33,8 @@ pub enum PyPluginError { /// 插件内函数调用错误 /// pyerr, func_name, module_name FuncCallError(pyo3::PyErr, String, String), + /// 插件停不下来! + PluginNotStopped, } impl From for IcaError { @@ -80,6 +82,9 @@ impl std::fmt::Display for PyPluginError { } PyPluginError::FuncCallError(py_err, name, module) => { write!(f, "插件内函数调用错误: {:#?}|{} in {}", py_err, name, module) + }, + PyPluginError::PluginNotStopped => { + write!(f, "插件未停止") } } } @@ -111,6 +116,7 @@ impl std::error::Error for PyPluginError { PyPluginError::CouldNotGetFunc(e, _, _) => Some(e), PyPluginError::FuncNotCallable(_, _) => None, PyPluginError::FuncCallError(e, _, _) => Some(e), + PyPluginError::PluginNotStopped => None, } } } diff --git a/ica-rs/src/main.rs b/ica-rs/src/main.rs index 1a6857c..f6cd464 100644 --- a/ica-rs/src/main.rs +++ b/ica-rs/src/main.rs @@ -17,6 +17,7 @@ mod ica; mod tailchat; use config::BotConfig; +use error::PyPluginError; use tracing::{event, span, Level}; pub static mut MAIN_STATUS: status::BotStatus = status::BotStatus { @@ -139,15 +140,30 @@ fn main() -> anyhow::Result<()> { tracing_subscriber::fmt().with_max_level(level).init(); - let _ = tokio::runtime::Builder::new_multi_thread() + let rt = tokio::runtime::Builder::new_multi_thread() .enable_all() .thread_name("shenbot-rs") .worker_threads(10) .build() - .unwrap() + .unwrap(); + + let result = rt .block_on(inner_main()); event!(Level::INFO, "shenbot-rs v{} exiting", VERSION); + + match result { + Ok(_) => {} + Err(e) => { + if let Some(PyPluginError::PluginNotStopped) = e.downcast_ref::() { + event!(Level::WARN, "Python 插件停不下来, 3s 后终止 tokio rt"); + rt.shutdown_timeout(Duration::from_secs(3)); + } else { + event!(Level::ERROR, "shenbot-rs v{} exiting with error: {}", VERSION, e); + } + } + } + Ok(()) } diff --git a/ica-rs/src/py/mod.rs b/ica-rs/src/py/mod.rs index 2817391..74763c3 100644 --- a/ica-rs/src/py/mod.rs +++ b/ica-rs/src/py/mod.rs @@ -15,6 +15,7 @@ use pyo3::types::PyTuple; use pyo3::{intern, prelude::*}; use tracing::{event, span, warn, Level}; +use crate::error::PyPluginError; use crate::MainStatus; const REQUIRE_CONFIG_FUNC_NAME: &str = "require_config"; @@ -575,18 +576,13 @@ pub async fn post_py() -> anyhow::Result<()> { status.config.sync_status_to_config(); status.config.write_to_default()?; - stop_tasks().await; - unsafe { - if !pyo3::ffi::Py_FinalizeEx() == 0 { - event!(Level::ERROR, "Python 退出失败 (不过应该无所谓)"); - } - } + stop_tasks().await?; Ok(()) } -async fn stop_tasks() { +async fn stop_tasks() -> Result<(), PyPluginError> { if call::PY_TASKS.lock().await.is_empty() { - return; + return Ok(()); } let waiter = tokio::spawn(async { call::PY_TASKS.lock().await.join_all().await; @@ -594,10 +590,11 @@ async fn stop_tasks() { tokio::select! { _ = waiter => { event!(Level::INFO, "Python 任务完成"); + Ok(()) } _ = tokio::signal::ctrl_c() => { - call::PY_TASKS.lock().await.cancel_all(); - event!(Level::INFO, "Python 任务被中断"); + event!(Level::WARN, "正在强制结束 Python 任务"); + Err(PyPluginError::PluginNotStopped) } } } diff --git a/news/0-9.md b/news/0-9.md index 94697fe..6617605 100644 --- a/news/0-9.md +++ b/news/0-9.md @@ -2,6 +2,8 @@ ## 0.9.0 +- 修复了 Python 插件停不下来就真的停不下来的问题 + ### ica 2.0.1 > 添加了 `Room` 相关的 api