Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serialisation struggles with shell strings #2925

Open
lysogeny opened this issue Nov 10, 2023 · 9 comments
Open

Serialisation struggles with shell strings #2925

lysogeny opened this issue Nov 10, 2023 · 9 comments

Comments

@lysogeny
Copy link

Hey there!

I love the new resurrection feature. Unfortunately I managed to find a bug in the serialisation. When resurrection a session that includes pipes and strings, the session runs a command with the wrong arguments.

For example, running

dmesg -w --color=always | grep --color=never -P '(oom|Out of memory)'

in a shell, quitting the session and resurrecting it produces unexpected behaviour. In this example, grep returns

grep: missing closing parenthesis

Basic information

zellij --version:

zellij 0.39.0

stty size:

63 271

uname -av or ver(Windows):

Linux vm-129-69.cloud.dkfz-heidelberg.de 6.5.5-200.fc38.x86_64 #1 SMP PREEMPT_DYNAMIC Sun Sep 24 15:52:44 UTC 2023 x86_64 GNU/Linux

Other software

dmesg --version:

dmesg from util-linux 2.38.1

grep --version:

grep (GNU grep) 3.8
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and others; see
<https://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.

zsh --version:

zsh 5.9 (x86_64-redhat-linux-gnu)

Further information

How to reproduce:

# start a session
zellij -s serial-bug 
# run a fancy command
dmesg -w --color=always | grep --color=never -P '(oom|Out of memory)' 
# Now quit (e.g. C-q)
# Re-attach
zellij a serial-bug
# Hit enter to re-run the command

Produces:

grep: missing closing parenthesis

Notably, the pane is also called grep --color=auto --color=never -P (oom|Out of memory)

This appears to be because the pipe and ' are being incorrectly serialised:

% cat ~/.cache/zellij/0.39.0/session_info/serial-bug/session-layout.kdl
layout {
    tab name="Tab #1" focus=true hide_floating_panes=true {
        pane size=1 borderless=true {
            plugin location="zellij:tab-bar"
        }
        pane command="grep" cwd="/var/home/ada" focus=true {
            args "--color=auto" "--color=never" "-P" "(oom|Out" "of" "memory)"
            start_suspended true
        }
        pane size=2 borderless=true {
            plugin location="zellij:status-bar"
        }
    }
    new_tab_template {
        pane size=1 borderless=true {
            plugin location="zellij:tab-bar"
        }
        pane cwd="/var/home/ada"
        pane size=2 borderless=true {
            plugin location="zellij:status-bar"
        }
    }
}%       

Note how the command for the pane is grep and the string got mangled:

            args "--color=auto" "--color=never" "-P" "(oom|Out" "of" "memory)"

If I replace this with

            args "--color=auto" "--color=never" "-P" "(oom|Out of memory)"

grep works without errors, but is missing the dmesg input. I don't know to what extent this is fixeable but figured I should still report it.

Thank you for your time!

@zeratax
Copy link

zeratax commented Dec 1, 2023

yeah this is a big issue for me on nixos where lots of programs are wrapped.

if i have something running like nvim . it gets serialized as

 /home/nixos/.nix-profile/bin/nvim --cmd lua vim.g.node_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9.1/bin/nvim-node';vim.g.loaded_python_provider=0;vim.g.python3_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9.1/bin/nvim-python3';vim.g.ruby_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9

nvim here is just a shell script that sets a bunch of path variables and then executes

exec -a "$0" "/nix/store/az6kgqpgs570xbk0c2c3pl0jx4ncgxqd-neovim-unwrapped-0.9.1/bin/nvim"  --cmd "lua vim.g.node_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9.1/bin/nvim-node';vim.g.loaded_python_provider=0;vim.g.python3_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9.1/bin/nvim-python3';vim.g.ruby_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9.1/bin/nvim-ruby'" "$@"

but due to the missing quotation marks and the missing positional argument i can't enter my nvim session.

@rubenmate
Copy link

yeah this is a big issue for me on nixos where lots of programs are wrapped.

if i have something running like nvim . it gets serialized as

 /home/nixos/.nix-profile/bin/nvim --cmd lua vim.g.node_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9.1/bin/nvim-node';vim.g.loaded_python_provider=0;vim.g.python3_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9.1/bin/nvim-python3';vim.g.ruby_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9

nvim here is just a shell script that sets a bunch of path variables and then executes

exec -a "$0" "/nix/store/az6kgqpgs570xbk0c2c3pl0jx4ncgxqd-neovim-unwrapped-0.9.1/bin/nvim"  --cmd "lua vim.g.node_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9.1/bin/nvim-node';vim.g.loaded_python_provider=0;vim.g.python3_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9.1/bin/nvim-python3';vim.g.ruby_host_prog='/nix/store/qmqip8ajqhzmf3gs68y8177nw7s56bd2-neovim-0.9.1/bin/nvim-ruby'" "$@"

but due to the missing quotation marks and the missing positional argument i can't enter my nvim session.

So this is why all my nix installed packages aren't resurrecting.

Hope this can be solved, for me the resurrection just doesn't do it right now. I have to drop the shells because the resurrection command it's not what I want.

@Tanish2002
Copy link

Has anyone has found a workaround to this(nixos) for now? on tmux-resurrect I could setup a resurrect-hook-post-save-all to manually fix the issues.

@hmajid2301
Copy link

hmajid2301 commented Apr 10, 2024

@imsnif Hey, sorry to bother you, I am trying to have a look at this and trying to see if the issue is with the serialization and particularly splitting the args on whitespace.

I am wondering where I should be looking. I am currently in looking over here:

fn extract_command_and_args(layout_run: &Option<Run>) -> (Option<String>, Vec<String>) {
match layout_run {
Some(Run::Command(run_command)) => (
Some(run_command.command.display().to_string()),
run_command.args.clone(),
),
_ => (None, vec![]),
}
}
.

I am not a rust developer 😓 so trying my best to follow the code.

Could you provide a bit of guidance if I am looking in the right place 🙏 .

Thank you very much, I appreciate you are very busy!

@sinh-x
Copy link

sinh-x commented Jul 14, 2024

I wonder if I can resurrect the sessions with pane layout without rerun previous command? Can it make an options so I don't have to go to each pane and press ESC on each pane?

@monk3yd
Copy link

monk3yd commented Jul 30, 2024

Same issue here

@mikebcbc
Copy link

Following. Same here.

@imsnif
Copy link
Member

imsnif commented Oct 2, 2024

These have been (mostly) fixed by #3636 (still unreleased but just merged to main).

I say "mostly" because what the PR fixed is the serialization part, the session-serialization still relies on the system's perspective of the running process (at the time of writing gleaned through ps) in order to determine what's running inside a pane.

To give an example, in the original report, the command: dmesg -w --color=always | grep --color=never -P '(oom|Out of memory)'. Here, we see a pipeline managed by the user's shell (eg. bash). From the perspective of the system, what we'll see is the last foreground command (in this case grep)*. So the resurrection will assume what's running inside the pane is the grep command.

Other examples might be various applications that run inside some sort of wrapper (eg. nix, electron, node, various java runtimes, etc.)

While there are ways around this, they are often particular to the task at hand. Maintaining a list of ways this information can be found and linking it to the particular command type is out of scope for Zellij core. In the future, I hope to add to the plugin API to allow plugins to optionally add other methods of doing this. For now, I feel this solution is good for the vast majority of cases.

*I hope readers will forgive me this simplification

@ruslanSorokin
Copy link

Has anyone has found a workaround to this(nixos) for now? on tmux-resurrect I could setup a resurrect-hook-post-save-all to manually fix the issues.

I'm using neovim-unwrapped. It comes with an ELF executable as the entry point, unlike the bash script in neovim, so there's no issue with missing double quotes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants