refactor(core): stabilize 'static backing for sidecar logging

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<str>`, 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.
This commit is contained in:
Slinetrac
2025-10-09 16:46:11 +08:00
parent e3cd16189b
commit fe7eb59f18

View File

@@ -57,6 +57,28 @@ impl fmt::Display for RunningMode {
use crate::config::IVerge; 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 { impl CoreManager {
/// 检查文件是否为脚本文件 /// 检查文件是否为脚本文件
fn is_script_file(&self, path: &str) -> Result<bool> { fn is_script_file(&self, path: &str) -> Result<bool> {
@@ -771,48 +793,26 @@ impl CoreManager {
match event { match event {
tauri_plugin_shell::process::CommandEvent::Stdout(line) => { tauri_plugin_shell::process::CommandEvent::Stdout(line) => {
let mut now = DeferredNow::default(); let mut now = DeferredNow::default();
let line_str = String::from_utf8_lossy(&line); let message = String::from_utf8_lossy(&line).into_owned();
let arg = format_args!("{}", line_str); let message = write_sidecar_log(&*w, &mut now, log::Level::Error, message);
let record = Record::builder() Logger::global().append_log(message);
.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());
} }
tauri_plugin_shell::process::CommandEvent::Stderr(line) => { tauri_plugin_shell::process::CommandEvent::Stderr(line) => {
let mut now = DeferredNow::default(); let mut now = DeferredNow::default();
let line_str = String::from_utf8_lossy(&line); let message = String::from_utf8_lossy(&line).into_owned();
let arg = format_args!("{}", line_str); let message = write_sidecar_log(&*w, &mut now, log::Level::Error, message);
let record = Record::builder() Logger::global().append_log(message);
.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());
} }
tauri_plugin_shell::process::CommandEvent::Terminated(term) => { tauri_plugin_shell::process::CommandEvent::Terminated(term) => {
let mut now = DeferredNow::default(); 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) format!("Process terminated with code: {}", code)
} else if let Some(signal) = term.signal { } else if let Some(signal) = term.signal {
format!("Process terminated by signal: {}", signal) format!("Process terminated by signal: {}", signal)
} else { } else {
"Process terminated".to_string() "Process terminated".to_string()
}; };
let arg = format_args!("{}", output_str); write_sidecar_log(&*w, &mut now, log::Level::Info, message);
let record = Record::builder()
.args(arg)
.level(log::Level::Info)
.target("sidecar")
.build();
let _ = w.write(&mut now, &record);
break; break;
} }
_ => {} _ => {}