From 133e359d70df055bd717ad88b7fe9bd5b3a5d5d0 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 12 Feb 2022 11:41:03 -0800 Subject: [PATCH] Add a test that stdin is always handed-off as blocking No functional change here, just closing a gap in our coverage. --- src/fish_test_helper.cpp | 18 +++++++++++++ tests/pexpects/stdin_nonblocking.py | 39 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 tests/pexpects/stdin_nonblocking.py diff --git a/src/fish_test_helper.cpp b/src/fish_test_helper.cpp index af9ca427b..d8da3f6cc 100644 --- a/src/fish_test_helper.cpp +++ b/src/fish_test_helper.cpp @@ -156,6 +156,22 @@ static void sigkill_self() { abort(); } +static void stdin_make_nonblocking() { + const int fd = STDIN_FILENO; + // Catch SIGCONT so pause() wakes us up. + signal(SIGCONT, [](int) {}); + + for (;;) { + int flags = fcntl(fd, F_GETFL, 0); + fprintf(stdout, "stdin was %sblocking\n", (flags & O_NONBLOCK) ? "non" : ""); + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + perror("fcntl"); + exit(EXIT_FAILURE); + } + pause(); + } +} + static void show_help(); /// A thing that fish_test_helper can do. @@ -188,6 +204,8 @@ static fth_command_t s_commands[] = { "Print to stdout the name(s) of ignored signals"}, {"print_stop_cont", print_stop_cont, "Print when we get SIGTSTP and SIGCONT, exiting on input"}, {"sigkill_self", sigkill_self, "Send SIGKILL to self"}, + {"stdin_make_nonblocking", stdin_make_nonblocking, + "Print if stdin is blocking and then make it nonblocking"}, {"help", show_help, "Print list of fish_test_helper commands"}, }; diff --git a/tests/pexpects/stdin_nonblocking.py b/tests/pexpects/stdin_nonblocking.py new file mode 100644 index 000000000..fac8744a2 --- /dev/null +++ b/tests/pexpects/stdin_nonblocking.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# Verify that stdin is properly set to blocking even if a job tweaks it. +from pexpect_helper import SpawnedProc +import sys +import signal +import time +import os + +sp = SpawnedProc() +send, sendline, expect_prompt, expect_str, sleep = ( + sp.send, + sp.sendline, + sp.expect_prompt, + sp.expect_str, + sp.sleep, +) + +# Launch fish_test_helper. +expect_prompt() +exe_path = os.environ.get("fish_test_helper") +sendline(exe_path + " stdin_make_nonblocking") + +expect_str("stdin was blocking") +sleep(0.1) + +send("\x1A") # ctrl-Z +expect_prompt("has stopped") + +# We don't "restore" non-blocking state when continuing a stopped job. +sleep(0.1) +sendline("fg") +expect_str("stdin was blocking") + +# Kill the job and do it again. +send("\x03") # ctrl-c +expect_prompt("") +sendline(exe_path + " stdin_make_nonblocking") +expect_str("stdin was blocking") +send("\x03") # ctrl-c