terminal
terminal copied to clipboard
Terminal freezes when closing with the close button
What Happened?
I have a terminal with only one tabs left and nothing except zsh itself running and I want to close the terminal with the close button (both the one from the tab and the one from the window is okay), but the terminal freezes.
After some quick scan of the code, insert some debug lines and some rebuild etc. I noticed that it freezes because of:
https://github.com/elementary/terminal/blob/5a9ac9197e89191c1477a3ae0d7d694dd152365b/src/Widgets/TerminalWidget.vala#L307-L316
I actually insert this line above Thread.usleep (100);
:
warning (this.child_pid.to_string ());
to get the pid and ran e.g. ps -Al | grep 85231
and it is zsh and it is a zombie process, so we cannot get rid of the while loop and the terminal freezes. Unfortunately, after changing zsh to bash, I can still trigger the issue in the same way so I actually don't think it is related to what shell I am using.
I was aware that many years ago, there is a commit https://github.com/elementary/terminal/commit/ad127db5fc6088eba5379c4d8002074e83054bb7 that introduces this situation, and reverting https://github.com/elementary/terminal/commit/ad127db5fc6088eba5379c4d8002074e83054bb7 of course resolves the issue for me since we can break the loop eventually.
Also by using Ctrl + D or the exit
command you can still close the terminal without issues.
It can be very possible that this can be cannot reproduced on elementary OS because I only saw this issue recently on a NixOS unstable + Pantheon system with GNOME 43 packages shipped. It can be possible that some GNOME 43 packages break this but also possible that some random changes break this. The testing is done in both a clean VM and my laptop.
Thanks for reading this!
Steps to Reproduce
If you need a NixOS Pantheon VM (on elementary OS) you can follow https://github.com/elementary/gala/issues/1214#issuecomment-970091146 and use nix --experimental-features "nix-command flakes" run github:bobby285271/test-pantheon --override-input nixpkgs github:NixOS/nixpkgs/pull/182618/head
.
- Open the terminal
- Close the terminal with the close button
Expected Behavior
The terminal closes and no freeze.
OS Version
Other Linux
Software Version
Latest release (I have run all updates)
Log Output
No response
Hardware Info
No response
So the issue is that the tab cannot be closed with the close button if the child is a zombie? Do you know why the child became zombified? Is there a way of detecting a zombie in code?
I actually don't know why it becomes a zombie :-(
If the cause is external to Terminal/Elementary, then throwing that dialog with a Force Quit option seems a reasonable response pro temp pending an upstream fix. Otherwise we need to stop the zombification.
:disappointed: Yeah I am still looking into it, it seems that it only becomes a zombie when the first Posix.kill (this.child_pid, Posix.Signal.HUP);
happened and it was not zombie before. Actually this is what I did:
public void term_ps () {
killed = true;
warning (this.child_pid.to_string ());
Thread.usleep (10000000);
Posix.kill (this.child_pid, Posix.Signal.HUP);
// Posix.kill (this.child_pid, Posix.Signal.TERM);
warning ("Done");
while (true) { }
}
Do you have any suggestions on how to debug this? I actually tried launching a random zenity process (outside of the elementary terminal), get the pid and replace this.child_pid
with it like:
public void term_ps () {
killed = true;
// warning (this.child_pid.to_string ());
Thread.usleep (10000000);
Posix.kill (145200, Posix.Signal.HUP);
// Posix.kill (this.child_pid, Posix.Signal.TERM);
warning ("Done");
while (true) { }
}
While the terminal still freeze (as expected) Posix.kill
actually successfully hang up the zenity process.
Update: Also tried using a pid from a zsh which is launched in a xterm terminal, with the same steps Posix.kill
is still able to hang up the external zsh.
I'll have a look into it and see if I can reproduce. Perhaps we should not be able to close a tab with running child anyway? What becomes of a the child process if Terminal is terminated some other way?
What setting save-exited-tabs
do you have? If this is true then the shell process for closed tabs will continue until the Terminal window is closed and when that tab is restored no new shell process is created. The default setting on Elementary is true
.
I have switch my default shell to zsh but as yet not reproduced the freeze.
Can you reproduce this on NixOS using bash
as the shell?
Can you reproduce this on NixOS using bash
as the shell?
gsettings get io.elementary.terminal.settings save-exited-tabs
gave me true
. Yeah it can be possible that those GNOME 43 packages are needed to reproduce the issue :-(
Can you reproduce this on NixOS using bash as the shell?
Yes (actually my laptop is using zsh but the screenshot above is a VM that uses bash)
Unfortunately the commit that introduced this possibility of an infinite loop by removing the maximum number of tries to kill the shell process is too old for me to find out what issue this was supposed to fix. It would seem sensible to impose a maximum number of retries.
In most cases the user will "Force Quit" anyway so there seems little harm in doing it code?
Just tried commenting out the while of that loop so Terminal no longer tries to close the shell process. The processes and any child processes get closed anyway so :shrug:
Can https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2408 be the reason of this issue? I actually did some bisect and noticed that MR.
/cc @jtojnar
Hmmm... So maybe this will be another possible workaround?
public void term_ps () {
killed = true;
Posix.kill (this.child_pid, Posix.Signal.HUP);
Posix.kill (this.child_pid, Posix.Signal.TERM);
int status;
Posix.waitpid (this.child_pid, out status, 0);
}
From my testing the terminal will no longer freeze when closing but you will get a new warning (when closing the terminal) if you build it with GLib 2.72.3
[GLib] GChildWatchSource: Exit status of a child process was requested but ECHILD was received by waitpid(). See the documentation of g_child_watch_source_new() for possible causes.
The warning does not present if you build with GLib 2.74.0 however.
~~Okay, sounds like waitpid is the correct way, let's just do this conditionally: https://github.com/cockpit-project/cockpit/pull/17564~~ Ah no, see the PR below, which uses pidfd
I'm also experiencing this freeze when trying to close the terminal -- though I'm not running the official distro of Elementary, I'm running Pantheon on my Arch install.