From fe7eb59f18485586fe07e9487c3192808e5fcf91 Mon Sep 17 00:00:00 2001 From: Slinetrac Date: Thu, 9 Oct 2025 16:46:11 +0800 Subject: [PATCH] refactor(core): stabilize 'static backing for sidecar logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduced `write_sidecar_log` to prevent temporary `format_args!` values from dropping early. - src-tauri/src/core/core.rs:60 — adds `write_sidecar_log`, which temporarily leaks the message into a `Box`, builds the `Record`, writes it, then immediately reclaims the boxed string. The `unsafe` block is limited to `Box::from_raw` needed to undo `Box::leak`. - src-tauri/src/core/core.rs:794, 802, 806 — all three sidecar events now route through this helper, reusing the returned string for the in-memory log and avoiding extra UTF-8 decoding. --- src-tauri/src/core/core.rs | 60 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index eca22d29..2728276c 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -57,6 +57,28 @@ impl fmt::Display for RunningMode { use crate::config::IVerge; +fn write_sidecar_log( + writer: &dyn LogWriter, + now: &mut DeferredNow, + level: log::Level, + message: String, +) -> String { + let boxed = message.into_boxed_str(); + let leaked = Box::leak(boxed); + let leaked_ptr = leaked as *mut str; + let args = format_args!("{}", leaked); + { + let record = Record::builder() + .args(args) + .level(level) + .target("sidecar") + .build(); + let _ = writer.write(now, &record); + } + // SAFETY: `leaked` originated from `Box::leak` above; reboxing frees it immediately after use. + unsafe { String::from(Box::from_raw(leaked_ptr)) } +} + impl CoreManager { /// 检查文件是否为脚本文件 fn is_script_file(&self, path: &str) -> Result { @@ -771,48 +793,26 @@ impl CoreManager { match event { tauri_plugin_shell::process::CommandEvent::Stdout(line) => { let mut now = DeferredNow::default(); - let line_str = String::from_utf8_lossy(&line); - let arg = format_args!("{}", line_str); - let record = Record::builder() - .args(arg) - .level(log::Level::Error) - .target("sidecar") - .build(); - let _ = w.write(&mut now, &record); - - let line = String::from_utf8_lossy(&line); - Logger::global().append_log(line.to_string()); + let message = String::from_utf8_lossy(&line).into_owned(); + let message = write_sidecar_log(&*w, &mut now, log::Level::Error, message); + Logger::global().append_log(message); } tauri_plugin_shell::process::CommandEvent::Stderr(line) => { let mut now = DeferredNow::default(); - let line_str = String::from_utf8_lossy(&line); - let arg = format_args!("{}", line_str); - let record = Record::builder() - .args(arg) - .level(log::Level::Error) - .target("sidecar") - .build(); - let _ = w.write(&mut now, &record); - - let line = String::from_utf8_lossy(&line); - Logger::global().append_log(line.to_string()); + let message = String::from_utf8_lossy(&line).into_owned(); + let message = write_sidecar_log(&*w, &mut now, log::Level::Error, message); + Logger::global().append_log(message); } tauri_plugin_shell::process::CommandEvent::Terminated(term) => { let mut now = DeferredNow::default(); - let output_str = if let Some(code) = term.code { + let message = if let Some(code) = term.code { format!("Process terminated with code: {}", code) } else if let Some(signal) = term.signal { format!("Process terminated by signal: {}", signal) } else { "Process terminated".to_string() }; - let arg = format_args!("{}", output_str); - let record = Record::builder() - .args(arg) - .level(log::Level::Info) - .target("sidecar") - .build(); - let _ = w.write(&mut now, &record); + write_sidecar_log(&*w, &mut now, log::Level::Info, message); break; } _ => {}