mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 14:51:03 +00:00
fix: avoid UI-dependent async APIs from being called during app initialization to avoid deadlocks (#3445)
This commit is contained in:
parent
e9eb8b9155
commit
e7cd66370f
6 changed files with 49 additions and 25 deletions
|
|
@ -1 +1 @@
|
|||
{"version":"0.2","flagWords":[],"language":"en","words":["Punct","KEYMAP","splitn","crossterm","YAZI","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","Konsole","Überzug","pkgs","pdftoppm","poppler","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","ffprobe","vframes","luma","obase","outln","errln","tmtheme","twox","cfgs","fstype","objc","rdev","runloop","exfat","rclone","DECRQSS","DECSCUSR","libvterm","Uninit","lockin","rposition","resvg","foldhash","tilded","futs","chdir","hashbrown","JEMALLOC","RUSTFLAGS","RDONLY","GETPATH","fcntl","casefold","inodes","Splatable","casefied","thiserror","memchr","memmem","russh","deadpool","keepalive","nodelay","publickey","deadpool"]}
|
||||
{"flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","Konsole","Überzug","pkgs","pdftoppm","poppler","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","ffprobe","vframes","luma","obase","outln","errln","tmtheme","twox","cfgs","fstype","objc","rdev","runloop","exfat","rclone","DECRQSS","DECSCUSR","libvterm","Uninit","lockin","rposition","resvg","foldhash","tilded","futs","chdir","hashbrown","JEMALLOC","RUSTFLAGS","RDONLY","GETPATH","fcntl","casefold","inodes","Splatable","casefied","thiserror","memchr","memmem","russh","deadpool","keepalive","nodelay","publickey","deadpool","initing"],"version":"0.2","language":"en"}
|
||||
|
|
@ -3,10 +3,11 @@ use std::collections::VecDeque;
|
|||
use hashbrown::HashMap;
|
||||
use mlua::Function;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug)]
|
||||
pub struct Runtime {
|
||||
frames: VecDeque<RuntimeFrame>,
|
||||
blocks: HashMap<String, Vec<Function>>,
|
||||
frames: VecDeque<RuntimeFrame>,
|
||||
blocks: HashMap<String, Vec<Function>>,
|
||||
pub initing: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -16,10 +17,13 @@ struct RuntimeFrame {
|
|||
}
|
||||
|
||||
impl Runtime {
|
||||
pub fn new(id: &str) -> Self {
|
||||
pub fn new() -> Self { Self { frames: <_>::default(), blocks: <_>::default(), initing: true } }
|
||||
|
||||
pub fn new_isolate(id: &str) -> Self {
|
||||
Self {
|
||||
frames: VecDeque::from([RuntimeFrame { id: id.to_owned(), calls: 0 }]),
|
||||
..Default::default()
|
||||
frames: VecDeque::from([RuntimeFrame { id: id.to_owned(), calls: 0 }]),
|
||||
blocks: <_>::default(),
|
||||
initing: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::borrow::Cow;
|
|||
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, ObjectLike, Table, Value};
|
||||
use tracing::error;
|
||||
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
||||
use yazi_binding::{Composer, ComposerGet, ComposerSet, Permit, PermitRef, elements::{Line, Rect, Span}};
|
||||
use yazi_binding::{Composer, ComposerGet, ComposerSet, Permit, PermitRef, elements::{Line, Rect, Span}, runtime};
|
||||
use yazi_config::LAYOUT;
|
||||
use yazi_proxy::{AppProxy, HIDER};
|
||||
use yazi_shared::replace_to_printable;
|
||||
|
|
@ -44,6 +44,10 @@ pub(super) fn area(lua: &Lua) -> mlua::Result<Value> {
|
|||
|
||||
pub(super) fn hide(lua: &Lua) -> mlua::Result<Value> {
|
||||
let f = lua.create_async_function(|lua, ()| async move {
|
||||
if runtime!(lua)?.initing {
|
||||
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()) {
|
||||
return Err("Cannot hide while already hidden".into_lua_err());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use yazi_macro::plugin_preset as preset;
|
|||
|
||||
pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
|
||||
let lua = Lua::new();
|
||||
lua.set_app_data(Runtime::new(name));
|
||||
lua.set_app_data(Runtime::new_isolate(name));
|
||||
|
||||
// Base
|
||||
let globals = lua.globals();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use anyhow::{Context, Result};
|
||||
use futures::executor::block_on;
|
||||
use mlua::Lua;
|
||||
use yazi_binding::Runtime;
|
||||
use yazi_binding::{Runtime, runtime_mut};
|
||||
use yazi_boot::BOOT;
|
||||
use yazi_macro::plugin_preset as preset;
|
||||
use yazi_shared::RoCell;
|
||||
|
|
@ -17,7 +17,7 @@ pub(super) fn init_lua() -> Result<()> {
|
|||
}
|
||||
|
||||
fn stage_1(lua: &'static Lua) -> Result<()> {
|
||||
lua.set_app_data(Runtime::default());
|
||||
lua.set_app_data(Runtime::new());
|
||||
|
||||
// Base
|
||||
let globals = lua.globals();
|
||||
|
|
@ -67,5 +67,6 @@ fn stage_2(lua: &'static Lua) -> mlua::Result<()> {
|
|||
block_on(lua.load(b).set_name("init.lua").exec_async())?;
|
||||
}
|
||||
|
||||
runtime_mut!(lua)?.initing = false;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::{str::FromStr, time::Duration};
|
|||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, Table, Value};
|
||||
use tokio::sync::mpsc;
|
||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||
use yazi_binding::{deprecate, elements::{Line, Pos, Text}};
|
||||
use yazi_binding::{deprecate, elements::{Line, Pos, Text}, runtime};
|
||||
use yazi_config::{keymap::{Chord, Key}, popup::{ConfirmCfg, InputCfg}};
|
||||
use yazi_macro::relay;
|
||||
use yazi_parser::which::ShowOpt;
|
||||
|
|
@ -15,20 +15,27 @@ use crate::bindings::InputRx;
|
|||
|
||||
impl Utils {
|
||||
pub(super) fn which(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|_, t: Table| async move {
|
||||
let (tx, mut rx) = mpsc::channel::<usize>(1);
|
||||
|
||||
let mut cands = Vec::with_capacity(30);
|
||||
for (i, cand) in t.raw_get::<Table>("cands")?.sequence_values::<Table>().enumerate() {
|
||||
let cand = cand?;
|
||||
cands.push(Chord {
|
||||
on: Self::parse_keys(cand.raw_get("on")?)?,
|
||||
run: vec![relay!(which:callback, [i]).with_any("tx", tx.clone())],
|
||||
desc: cand.raw_get("desc").ok(),
|
||||
r#for: None,
|
||||
});
|
||||
lua.create_async_function(|lua, t: Table| async move {
|
||||
if runtime!(lua)?.initing {
|
||||
return Err("Cannot call `ya.which()` during app initialization".into_lua_err());
|
||||
}
|
||||
|
||||
let (tx, mut rx) = mpsc::channel::<usize>(1);
|
||||
let cands: Vec<_> = t
|
||||
.raw_get::<Table>("cands")?
|
||||
.sequence_values::<Table>()
|
||||
.enumerate()
|
||||
.map(|(i, cand)| {
|
||||
let cand = cand?;
|
||||
Ok(Chord {
|
||||
on: Self::parse_keys(cand.raw_get("on")?)?,
|
||||
run: vec![relay!(which:callback, [i]).with_any("tx", tx.clone())],
|
||||
desc: cand.raw_get("desc").ok(),
|
||||
r#for: None,
|
||||
})
|
||||
})
|
||||
.collect::<mlua::Result<_>>()?;
|
||||
|
||||
drop(tx);
|
||||
WhichProxy::show(ShowOpt { cands, silent: t.raw_get("silent").unwrap_or_default() });
|
||||
|
||||
|
|
@ -38,6 +45,10 @@ impl Utils {
|
|||
|
||||
pub(super) fn input(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|lua, t: Table| async move {
|
||||
if runtime!(lua)?.initing {
|
||||
return Err("Cannot call `ya.input()` during app initialization".into_lua_err());
|
||||
}
|
||||
|
||||
let mut pos = t.raw_get::<Value>("pos")?;
|
||||
if pos.is_nil() {
|
||||
pos = t.raw_get("position")?;
|
||||
|
|
@ -80,7 +91,11 @@ impl Utils {
|
|||
})
|
||||
}
|
||||
|
||||
lua.create_async_function(|_, t: Table| async move {
|
||||
lua.create_async_function(|lua, t: Table| async move {
|
||||
if runtime!(lua)?.initing {
|
||||
return Err("Cannot call `ya.confirm()` during app initialization".into_lua_err());
|
||||
}
|
||||
|
||||
let result = ConfirmProxy::show(ConfirmCfg {
|
||||
position: Pos::try_from(t.raw_get::<Value>("pos")?)?.into(),
|
||||
title: Line::try_from(t.raw_get::<Value>("title")?)?.into(),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue