2020-06-13 21:38:54 +08:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
from pexpect_helper import SpawnedProc
|
|
|
|
|
2020-08-11 02:58:44 +08:00
|
|
|
sp = SpawnedProc(timeout=10)
|
2020-06-13 21:38:54 +08:00
|
|
|
send, sendline, sleep, expect_prompt, expect_re, expect_str = (
|
|
|
|
sp.send,
|
|
|
|
sp.sendline,
|
|
|
|
sp.sleep,
|
|
|
|
sp.expect_prompt,
|
|
|
|
sp.expect_re,
|
|
|
|
sp.expect_str,
|
|
|
|
)
|
|
|
|
|
|
|
|
from time import sleep
|
|
|
|
import os
|
2024-03-30 23:10:12 +08:00
|
|
|
import platform
|
2020-06-13 21:38:54 +08:00
|
|
|
import signal
|
|
|
|
import subprocess
|
2020-08-12 22:59:56 +08:00
|
|
|
import sys
|
2020-06-13 21:38:54 +08:00
|
|
|
|
2024-04-12 17:27:10 +08:00
|
|
|
if "CI" in os.environ and platform.system() == "Darwin":
|
|
|
|
sys.exit(127)
|
|
|
|
|
|
|
|
if platform.system() == "FreeBSD": # Spurious failure. TODO Only disable this in CI.
|
2024-03-30 23:10:12 +08:00
|
|
|
sys.exit(127)
|
|
|
|
|
2020-06-13 21:38:54 +08:00
|
|
|
expect_prompt()
|
|
|
|
|
2021-07-27 04:12:30 +08:00
|
|
|
# Verify that SIGINT inside a command sub cancels it.
|
|
|
|
# Negate the pid to send to the pgroup (which should include sleep).
|
2024-05-06 05:51:03 +08:00
|
|
|
sendline("while true; echo (sleep 2000); end")
|
2021-07-27 04:12:30 +08:00
|
|
|
sleep(0.5)
|
|
|
|
os.kill(-sp.spawn.pid, signal.SIGINT)
|
|
|
|
expect_prompt()
|
2024-05-08 22:35:00 +08:00
|
|
|
sleep(0.2)
|
2021-07-27 04:12:30 +08:00
|
|
|
|
2024-05-06 05:51:03 +08:00
|
|
|
# SIGINT should be ignored by background processes.
|
|
|
|
sendline("sleep 1234 &")
|
2020-06-13 21:38:54 +08:00
|
|
|
expect_prompt()
|
2024-05-06 05:51:03 +08:00
|
|
|
os.kill(-sp.spawn.pid, signal.SIGINT)
|
2024-05-07 23:08:09 +08:00
|
|
|
sleep(0.500)
|
2020-06-13 21:38:54 +08:00
|
|
|
sendline("jobs")
|
2024-05-06 05:51:03 +08:00
|
|
|
expect_prompt("sleep 1234")
|
2020-06-13 21:38:54 +08:00
|
|
|
sendline("kill %1")
|
2020-06-25 02:43:56 +08:00
|
|
|
expect_prompt()
|
2020-06-13 21:38:54 +08:00
|
|
|
|
|
|
|
# Verify that the fish_postexec handler is called after SIGINT.
|
|
|
|
sendline("function postexec --on-event fish_postexec; echo fish_postexec spotted; end")
|
|
|
|
expect_prompt()
|
|
|
|
sendline("read")
|
2024-05-16 16:52:19 +08:00
|
|
|
expect_re(r"\r\n?read> $", timeout=10)
|
2024-04-30 04:47:24 +08:00
|
|
|
sleep(0.1)
|
2020-06-13 21:38:54 +08:00
|
|
|
os.kill(sp.spawn.pid, signal.SIGINT)
|
2024-04-26 03:36:31 +08:00
|
|
|
expect_str("fish_postexec spotted", timeout=10)
|
2020-06-13 21:38:54 +08:00
|
|
|
expect_prompt()
|
|
|
|
|
2024-05-06 06:18:43 +08:00
|
|
|
# Ensure that we catch up.
|
|
|
|
sendline("echo 'hello' 'world'")
|
|
|
|
expect_prompt("hello world")
|
|
|
|
|
2020-06-13 21:38:54 +08:00
|
|
|
# Verify that the fish_kill_signal is set.
|
2020-06-25 02:43:56 +08:00
|
|
|
sendline(
|
|
|
|
"functions -e postexec; function postexec --on-event fish_postexec; echo fish_kill_signal $fish_kill_signal; end"
|
|
|
|
)
|
2024-05-06 06:18:43 +08:00
|
|
|
expect_prompt("fish_kill_signal 0")
|
2020-06-13 21:38:54 +08:00
|
|
|
sendline("sleep 5")
|
2024-04-24 02:38:09 +08:00
|
|
|
sleep(0.300)
|
2021-09-05 04:32:51 +08:00
|
|
|
subprocess.call(["pkill", "-INT", "-P", str(sp.spawn.pid), "sleep"])
|
2020-06-13 21:38:54 +08:00
|
|
|
expect_str("fish_kill_signal 2")
|
|
|
|
expect_prompt()
|
|
|
|
|
|
|
|
sendline("sleep 5")
|
2022-08-24 00:42:23 +08:00
|
|
|
sleep(0.200)
|
2022-06-17 00:43:28 +08:00
|
|
|
subprocess.call(["pkill", "-TERM", "-P", str(sp.spawn.pid), "sleep"])
|
2020-06-13 21:38:54 +08:00
|
|
|
expect_str("fish_kill_signal 15")
|
|
|
|
expect_prompt()
|
|
|
|
|
2024-01-23 23:38:03 +08:00
|
|
|
# See that open() is only interruptible by SIGINT.
|
|
|
|
sendline("mkfifo fifoo")
|
|
|
|
expect_prompt()
|
|
|
|
sendline("cat >fifoo")
|
|
|
|
subprocess.call(["kill", "-WINCH", str(sp.spawn.pid)])
|
|
|
|
expect_re("open: ", shouldfail=True, timeout=10)
|
|
|
|
subprocess.call(["kill", "-INT", str(sp.spawn.pid)])
|
|
|
|
expect_prompt()
|
|
|
|
|
2020-06-13 21:38:54 +08:00
|
|
|
# Verify that sending SIGHUP to the shell, such as will happen when the tty is
|
|
|
|
# closed by the terminal, terminates the shell and the foreground command and
|
|
|
|
# any background commands run from that shell.
|
2022-08-24 00:42:23 +08:00
|
|
|
#
|
|
|
|
# Save the pids for later to check if they are still running.
|
|
|
|
pids = []
|
2024-05-06 06:18:43 +08:00
|
|
|
send("sleep 1300 & echo $last_pid\r")
|
2024-04-03 04:40:45 +08:00
|
|
|
pids += [expect_re("\\d+\r\n").group().strip()]
|
2020-06-13 21:38:54 +08:00
|
|
|
expect_prompt()
|
2024-05-06 06:18:43 +08:00
|
|
|
sendline("echo 'catch' 'up' 'A'")
|
|
|
|
expect_prompt("catch up A")
|
|
|
|
send("sleep 1310 & echo $last_pid\r")
|
2024-04-03 04:40:45 +08:00
|
|
|
pids += [expect_re("\\d+\r\n").group().strip()]
|
2020-06-13 21:38:54 +08:00
|
|
|
expect_prompt()
|
2024-05-06 06:18:43 +08:00
|
|
|
sendline("echo 'catch' 'up' 'B'")
|
|
|
|
expect_prompt("catch up B")
|
2020-08-30 06:43:43 +08:00
|
|
|
send("sleep 9999999\r")
|
2023-01-18 23:48:49 +08:00
|
|
|
sleep(0.500) # ensure fish kicks off the above sleep before it gets HUP - see #7288
|
2020-06-13 21:38:54 +08:00
|
|
|
os.kill(sp.spawn.pid, signal.SIGHUP)
|
|
|
|
|
|
|
|
# Verify the spawned fish shell has exited.
|
|
|
|
sp.spawn.wait()
|
|
|
|
|
|
|
|
# Verify all child processes have been killed. We don't use `-p $pid` because
|
|
|
|
# if the shell has a bug the child processes might have been reparented to pid
|
|
|
|
# 1 rather than killed.
|
|
|
|
proc = subprocess.run(
|
|
|
|
["pgrep", "-l", "-f", "sleep 13"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
|
|
)
|
2022-08-24 00:42:23 +08:00
|
|
|
|
2023-06-02 00:20:19 +08:00
|
|
|
remaining = []
|
2020-06-13 21:38:54 +08:00
|
|
|
if proc.returncode == 0:
|
2022-08-24 00:42:23 +08:00
|
|
|
# If any sleeps exist, we check them against our pids,
|
|
|
|
# to avoid false-positives (any other `sleep 13xyz` running on the system)
|
2020-06-13 21:38:54 +08:00
|
|
|
print(proc.stdout)
|
2023-06-02 00:20:19 +08:00
|
|
|
for line in proc.stdout.split(b"\n"):
|
|
|
|
pid = line.split(b" ", maxsplit=1)[0].decode("utf-8")
|
2022-08-24 00:42:23 +08:00
|
|
|
if pid in pids:
|
|
|
|
remaining += [pid]
|
2023-06-02 00:20:19 +08:00
|
|
|
|
2022-08-24 00:42:23 +08:00
|
|
|
# Kill any remaining sleeps ourselves, otherwise rerunning this is pointless.
|
|
|
|
for pid in remaining:
|
|
|
|
try:
|
|
|
|
os.kill(int(pid), signal.SIGTERM)
|
|
|
|
except ProcessLookupError:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if remaining:
|
|
|
|
# We still have processes left over!
|
|
|
|
print("Commands were still running!")
|
|
|
|
print(remaining)
|
2020-06-13 21:38:54 +08:00
|
|
|
sys.exit(1)
|