mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
fix: a race condition when terminal resumes while signal system is restarting (#3448)
This commit is contained in:
parent
e7cd66370f
commit
329c5d28f0
14 changed files with 74 additions and 65 deletions
36
Cargo.lock
generated
36
Cargo.lock
generated
|
|
@ -585,9 +585,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.5.61"
|
||||
version = "4.5.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39615915e2ece2550c0149addac32fb5bd312c657f43845bb9088cb9c8a7c992"
|
||||
checksum = "004eef6b14ce34759aa7de4aea3217e368f463f46a3ed3764ca4b5a4404003b4"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
|
@ -3430,9 +3430,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392"
|
||||
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
|
@ -3874,9 +3874,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.9.8"
|
||||
version = "0.9.10+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8"
|
||||
checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde_core",
|
||||
|
|
@ -3889,33 +3889,33 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.7.3"
|
||||
version = "0.7.5+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533"
|
||||
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.4"
|
||||
version = "1.0.6+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e"
|
||||
checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_writer"
|
||||
version = "1.0.4"
|
||||
version = "1.0.6+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2"
|
||||
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.43"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647"
|
||||
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
|
|
@ -3947,9 +3947,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.35"
|
||||
version = "0.1.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c"
|
||||
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
|
|
@ -4747,6 +4747,7 @@ name = "yazi-binding"
|
|||
version = "25.9.15"
|
||||
dependencies = [
|
||||
"ansi-to-tui",
|
||||
"futures",
|
||||
"hashbrown 0.16.1",
|
||||
"mlua",
|
||||
"paste",
|
||||
|
|
@ -5075,18 +5076,17 @@ dependencies = [
|
|||
"anyhow",
|
||||
"async-priority-channel",
|
||||
"foldhash 0.2.0",
|
||||
"futures",
|
||||
"hashbrown 0.16.1",
|
||||
"libc",
|
||||
"lru 0.16.2",
|
||||
"mlua",
|
||||
"ordered-float 5.1.0",
|
||||
"parking_lot",
|
||||
"scopeguard",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"yazi-binding",
|
||||
"yazi-config",
|
||||
"yazi-dds",
|
||||
"yazi-fs",
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ thiserror = "2.0.17"
|
|||
tokio = { version = "1.48.0", features = [ "full" ] }
|
||||
tokio-stream = "0.1.17"
|
||||
tokio-util = "0.7.17"
|
||||
toml = { version = "0.9.8" }
|
||||
tracing = { version = "0.1.43", features = [ "max_level_debug", "release_max_level_debug" ] }
|
||||
toml = { version = "0.9.10" }
|
||||
tracing = { version = "0.1.44", features = [ "max_level_debug", "release_max_level_debug" ] }
|
||||
twox-hash = { version = "2.1.2", default-features = false, features = [ "std", "random", "xxhash3_128" ] }
|
||||
typed-path = "0.12.0"
|
||||
unicode-width = { version = "0.2.0", default-features = false }
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use crossterm::{execute, style::Print};
|
|||
use hashbrown::HashMap;
|
||||
use scopeguard::defer;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use yazi_binding::Permit;
|
||||
use yazi_config::{YAZI, opener::OpenerRule};
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_fs::{File, FilesOp, Splatter, max_common_root, path::skip_url, provider::{FileBuilder, Provider, local::{Gate, Local}}};
|
||||
|
|
@ -65,8 +66,7 @@ impl Actor for BulkRename {
|
|||
)
|
||||
.await;
|
||||
|
||||
let _permit = HIDER.acquire().await.unwrap();
|
||||
defer!(AppProxy::resume());
|
||||
let _permit = Permit::new(HIDER.acquire().await.unwrap(), AppProxy::resume());
|
||||
AppProxy::stop().await;
|
||||
|
||||
let new: Vec<_> = Local::regular(&tmp)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use anyhow::Result;
|
|||
use crossterm::{execute, terminal::{disable_raw_mode, enable_raw_mode}};
|
||||
use scopeguard::defer;
|
||||
use tokio::{io::{AsyncReadExt, stdin}, select, sync::mpsc, time};
|
||||
use yazi_binding::Permit;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::VoidOpt;
|
||||
use yazi_proxy::{AppProxy, HIDER};
|
||||
|
|
@ -26,7 +27,7 @@ impl Actor for Inspect {
|
|||
};
|
||||
|
||||
tokio::spawn(async move {
|
||||
let _permit = HIDER.acquire().await.unwrap();
|
||||
let _permit = Permit::new(HIDER.acquire().await.unwrap(), AppProxy::resume());
|
||||
let (tx, mut rx) = mpsc::unbounded_channel();
|
||||
|
||||
let buffered = {
|
||||
|
|
@ -37,9 +38,7 @@ impl Actor for Inspect {
|
|||
task.logs.clone()
|
||||
};
|
||||
|
||||
defer!(AppProxy::resume());
|
||||
AppProxy::stop().await;
|
||||
|
||||
terminal_clear(TTY.writer()).ok();
|
||||
TTY.writer().write_all(buffered.as_bytes()).ok();
|
||||
TTY.writer().flush().ok();
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ yazi-shared = { path = "../yazi-shared", version = "25.9.15" }
|
|||
|
||||
# External dependencies
|
||||
ansi-to-tui = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,42 +1,51 @@
|
|||
use std::{mem, ops::Deref};
|
||||
|
||||
use futures::{FutureExt, future::BoxFuture};
|
||||
use mlua::{UserData, prelude::LuaUserDataMethods};
|
||||
use tokio::sync::SemaphorePermit;
|
||||
|
||||
pub type PermitRef<F> = mlua::UserDataRef<Permit<F>>;
|
||||
pub type PermitRef = mlua::UserDataRef<Permit>;
|
||||
|
||||
pub struct Permit<F: FnOnce()> {
|
||||
pub struct Permit {
|
||||
inner: Option<SemaphorePermit<'static>>,
|
||||
destruct: Option<F>,
|
||||
destruct: Option<BoxFuture<'static, ()>>,
|
||||
}
|
||||
|
||||
impl<F: FnOnce()> Deref for Permit<F> {
|
||||
impl Deref for Permit {
|
||||
type Target = Option<SemaphorePermit<'static>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl<F: FnOnce()> Permit<F> {
|
||||
pub fn new(inner: SemaphorePermit<'static>, f: F) -> Self {
|
||||
Self { inner: Some(inner), destruct: Some(f) }
|
||||
impl Permit {
|
||||
pub fn new<F>(inner: SemaphorePermit<'static>, f: F) -> Self
|
||||
where
|
||||
F: Future<Output = ()> + 'static + Send,
|
||||
{
|
||||
Self { inner: Some(inner), destruct: Some(f.boxed()) }
|
||||
}
|
||||
|
||||
fn dropping(&mut self) {
|
||||
if let Some(f) = self.destruct.take() {
|
||||
f();
|
||||
}
|
||||
if let Some(p) = self.inner.take() {
|
||||
mem::drop(p);
|
||||
fn dropping(&mut self) -> impl Future<Output = ()> + 'static {
|
||||
let inner = self.inner.take();
|
||||
let destruct = self.destruct.take();
|
||||
|
||||
async move {
|
||||
if let Some(f) = destruct {
|
||||
f.await;
|
||||
}
|
||||
if let Some(p) = inner {
|
||||
mem::drop(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FnOnce()> Drop for Permit<F> {
|
||||
fn drop(&mut self) { self.dropping(); }
|
||||
impl Drop for Permit {
|
||||
fn drop(&mut self) { tokio::spawn(self.dropping()); }
|
||||
}
|
||||
|
||||
impl<F: FnOnce()> UserData for Permit<F> {
|
||||
impl UserData for Permit {
|
||||
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_method_mut("drop", |_, me, ()| Ok(me.dropping()));
|
||||
methods.add_async_method_mut("drop", |_, mut me, ()| async move { Ok(me.dropping().await) });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ yazi-shared = { path = "../yazi-shared", version = "25.9.15" }
|
|||
|
||||
# External dependencies
|
||||
clap = { workspace = true }
|
||||
clap_complete = "4.5.61"
|
||||
clap_complete = "4.5.62"
|
||||
clap_complete_fig = "4.5.2"
|
||||
clap_complete_nushell = "4.5.10"
|
||||
vergen-gitcl = { version = "1.0.8", features = [ "build", "rustc" ] }
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ yazi-shared = { path = "../yazi-shared", version = "25.9.15" }
|
|||
# External build dependencies
|
||||
anyhow = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
clap_complete = "4.5.61"
|
||||
clap_complete = "4.5.62"
|
||||
clap_complete_fig = "4.5.2"
|
||||
clap_complete_nushell = "4.5.10"
|
||||
serde_json = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ impl Signals {
|
|||
}
|
||||
});
|
||||
}
|
||||
SIGCONT if HIDER.try_acquire().is_ok() => AppProxy::resume(),
|
||||
SIGCONT if HIDER.try_acquire().is_ok() => _ = tokio::spawn(AppProxy::resume()),
|
||||
_ => {}
|
||||
}
|
||||
true
|
||||
|
|
|
|||
|
|
@ -48,14 +48,14 @@ pub(super) fn hide(lua: &Lua) -> mlua::Result<Value> {
|
|||
return Err("Cannot call `ui.hide()` during app initialization".into_lua_err());
|
||||
}
|
||||
|
||||
if lua.named_registry_value::<PermitRef<fn()>>("HIDE_PERMIT").is_ok_and(|h| h.is_some()) {
|
||||
if lua.named_registry_value::<PermitRef>("HIDE_PERMIT").is_ok_and(|h| h.is_some()) {
|
||||
return Err("Cannot hide while already hidden".into_lua_err());
|
||||
}
|
||||
|
||||
let permit = HIDER.acquire().await.unwrap();
|
||||
AppProxy::stop().await;
|
||||
|
||||
lua.set_named_registry_value("HIDE_PERMIT", Permit::new(permit, AppProxy::resume as fn()))?;
|
||||
lua.set_named_registry_value("HIDE_PERMIT", Permit::new(permit, AppProxy::resume()))?;
|
||||
lua.named_registry_value::<AnyUserData>("HIDE_PERMIT")
|
||||
})?;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,14 +35,14 @@ impl Utils {
|
|||
lua.create_async_function(|lua, ()| async move {
|
||||
deprecate!(lua, "`ya.hide()` is deprecated, use `ui.hide()` instead, in your {}\nSee #2939 for more details: https://github.com/sxyazi/yazi/pull/2939");
|
||||
|
||||
if lua.named_registry_value::<PermitRef<fn()>>("HIDE_PERMIT").is_ok_and(|h| h.is_some()) {
|
||||
if lua.named_registry_value::<PermitRef>("HIDE_PERMIT").is_ok_and(|h| h.is_some()) {
|
||||
return Err("Cannot hide while already hidden".into_lua_err());
|
||||
}
|
||||
|
||||
let permit = HIDER.acquire().await.unwrap();
|
||||
AppProxy::stop().await;
|
||||
|
||||
lua.set_named_registry_value("HIDE_PERMIT", Permit::new(permit, AppProxy::resume as fn()))?;
|
||||
lua.set_named_registry_value("HIDE_PERMIT", Permit::new(permit, AppProxy::resume()))?;
|
||||
lua.named_registry_value::<AnyUserData>("HIDE_PERMIT")
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ impl AppProxy {
|
|||
rx.await.ok();
|
||||
}
|
||||
|
||||
pub fn resume() {
|
||||
emit!(Call(relay!(app:resume)));
|
||||
pub async fn resume() {
|
||||
let (tx, rx) = oneshot::channel::<()>();
|
||||
emit!(Call(relay!(app:resume).with_any("tx", tx)));
|
||||
rx.await.ok();
|
||||
}
|
||||
|
||||
pub fn notify(opt: NotifyOpt) {
|
||||
|
|
|
|||
|
|
@ -12,27 +12,26 @@ repository = "https://github.com/sxyazi/yazi"
|
|||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
yazi-config = { path = "../yazi-config", version = "25.9.15" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.9.15" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.9.15" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.9.15" }
|
||||
yazi-parser = { path = "../yazi-parser", version = "25.9.15" }
|
||||
yazi-plugin = { path = "../yazi-plugin", version = "25.9.15" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "25.9.15" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.9.15" }
|
||||
yazi-vfs = { path = "../yazi-vfs", version = "25.9.15" }
|
||||
yazi-binding = { path = "../yazi-binding", version = "25.9.15" }
|
||||
yazi-config = { path = "../yazi-config", version = "25.9.15" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "25.9.15" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "25.9.15" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "25.9.15" }
|
||||
yazi-parser = { path = "../yazi-parser", version = "25.9.15" }
|
||||
yazi-plugin = { path = "../yazi-plugin", version = "25.9.15" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "25.9.15" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.9.15" }
|
||||
yazi-vfs = { path = "../yazi-vfs", version = "25.9.15" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
async-priority-channel = "0.2.0"
|
||||
foldhash = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
lru = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
ordered-float = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
scopeguard = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tokio-util = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::{Result, anyhow};
|
||||
use scopeguard::defer;
|
||||
use tokio::{io::{AsyncBufReadExt, BufReader}, select, sync::mpsc};
|
||||
use yazi_binding::Permit;
|
||||
use yazi_proxy::{AppProxy, HIDER};
|
||||
|
||||
use super::{ProcessInBg, ProcessInBlock, ProcessInOrphan, ShellOpt};
|
||||
|
|
@ -14,8 +14,7 @@ impl Process {
|
|||
pub(crate) fn new(ops: &mpsc::UnboundedSender<TaskOp>) -> Self { Self { ops: ops.into() } }
|
||||
|
||||
pub(crate) async fn block(&self, task: ProcessInBlock) -> Result<(), ProcessOutBlock> {
|
||||
let _permit = HIDER.acquire().await.unwrap();
|
||||
defer!(AppProxy::resume());
|
||||
let _permit = Permit::new(HIDER.acquire().await.unwrap(), AppProxy::resume());
|
||||
AppProxy::stop().await;
|
||||
|
||||
let (id, cmd) = (task.id, task.cmd.clone());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue