Ticket #4521 (closed defect: fixed)

Opened 22 months ago

Last modified 9 months ago

Really escape fish shell history

Reported by: htower Owned by: andrew_b
Priority: major Milestone: 4.8.32
Component: mc-core Version: master
Keywords: subshell, fish, history Cc: johannes
Blocked By: Blocking:
Branch state: merged Votes for changeset: committed-master

Description

Some of the "service" commands generated by the mc "leak" into the fish subshell history available to the user. An example to reproduce:

  • set user shell to fish and start mc (SHELL=/usr/bin/fish mc)
  • navigate to any directory
  • press Ctrl+o
  • press ↑ button (UP, go back in history)
  • observe " cd (printf '%b' ... " command

Older versions of fish shell ignored commands starting with a space (and did not show the discussed cd-commands), but after this issue, fixes were made that emulate the behavior of zsh's HIST_IGNORE_SPACE feature. So, we just have to use the zsh workaround for the fish shell as well.

The proposed patch has been tested with:

  • fish shell, version 3.6.1
  • mc, version 4.8.27
  • mc, 'master' git branch

Attachments

fish_cd_history.patch (1.1 KB) - added by htower 22 months ago.
fish_cd_history_v2.patch (1.9 KB) - added by htower 22 months ago.

Change History

Changed 22 months ago by htower

comment:1 Changed 22 months ago by htower

I'm sorry, I need to further test my fix, because maybe there are some problems that it introduces :(

comment:2 Changed 22 months ago by htower

Added an updated version of the fix.

After a deeper dive, more serious problems of the fish subshell were discovered, namely, incorrect execution of all types of commands coming from the Midnight Commander, not only fs-related "internal" commands (" cd ..."). An example of incorrect operation with a fish sub-shell:

  • set user shell to fish and start mc (SHELL=/usr/bin/fish mc)
  • type "pwd"
  • type "pwd" in the built-in command prompt and press Enter
  • repeat entering the "pwd" command several times, 4 for example
  • press Ctrl+o
  • In the shell output, it can be seen that the command was executed only in half of the cases, for our example with 4 commands there will be only 2 results

Experimentally, I found that for reliable operation, it is enough to add a "dummy" command ("\n", an empty in my fix) as the first one, after which all other sent lines are no longer ignored. This is probably not very nice and correct from a fundamental point of view, but finding the true cause requires significantly more time and effort, most likely you will have to figure out the code of the fish shell itself.

The proposed fix is tested for:

  • fish shell, versions 3.6.1 (c++), 3.7.0 (c++), git master (rust)
  • mc, version 4.8.30, git master

Changed 22 months ago by htower

comment:3 Changed 21 months ago by andrew_b

  • Status changed from new to accepted
  • Owner set to andrew_b
  • Branch state changed from no branch to on review
  • Milestone changed from Future Releases to 4.8.32

Thanks!

Branch: 4521_fish_history
changeset:8746c16ac1d7a68d1ac78cdacb639fe6cf5407f7

comment:4 Changed 21 months ago by andrew_b

  • Votes for changeset set to andrew_b
  • Branch state changed from on review to approved

comment:5 Changed 21 months ago by andrew_b

  • Status changed from accepted to testing
  • Votes for changeset changed from andrew_b to committed-master
  • Resolution set to fixed
  • Branch state changed from approved to merged

comment:6 Changed 21 months ago by andrew_b

  • Status changed from testing to closed

comment:7 Changed 9 months ago by ossi

my guess would be that there race condition between the shell discarding the input buffer after it displays the prompt, and mc feeding it commands. let's test it:

(echo " echo hello"; sleep 1; echo " echo world") | fish

nope, with fish 3.7.1 this executes both commands just fine.
... but only once the input is closed. this is certainly caused by input buffering of the pipe. and notably, it doesn't let itself convince otherwise with stdbuf, so it's definitely doing something non-standard.

note that fish is the only shell i tried that exposes this behavior - dash, bash, and zsh process the first command right away.

ok, let's try harder, then:

(echo " echo hello"; sleep 1; echo " echo world") | socat - EXEC:'fish -C \"sleep .5\"',pty,setsid,ctty

this reproduces mc's behavior more closely, and it still works just fine.

this experimentation can be taken further, if things still don't work when reverting the hack in mc.

comment:8 Changed 9 months ago by zaytsev

  • Cc johannes added

FYI

Note: See TracTickets for help on using tickets.