From e58bd8eea18bbdf30fd84f84f649ce8ba96eeb46 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Mon, 8 Jul 2024 02:53:52 +0900 Subject: [PATCH] kill: (test) add a case for testing -l 0xSIGMASK and -d $PID options Signed-off-by: Masatake YAMATO --- meson.build | 8 +++ tests/commands.sh | 1 + tests/expected/kill/decode | 20 ++++++++ tests/helpers/Makemodule.am | 4 ++ tests/helpers/test_sigstate.c | 94 +++++++++++++++++++++++++++++++++++ tests/ts/kill/decode | 69 +++++++++++++++++++++++++ 6 files changed, 196 insertions(+) create mode 100644 tests/expected/kill/decode create mode 100644 tests/helpers/test_sigstate.c create mode 100755 tests/ts/kill/decode diff --git a/meson.build b/meson.build index 883e79ad60..85c91e1c15 100644 --- a/meson.build +++ b/meson.build @@ -3649,6 +3649,14 @@ exe = executable( build_by_default: program_tests) exes += exe +exe = executable( + 'test_sigstate', + 'tests/helpers/test_sigstate.c', + include_directories : includes, + link_with : lib_common, + build_by_default: program_tests) +exes += exe + exe = executable( 'test_tiocsti', 'tests/helpers/test_tiocsti.c', diff --git a/tests/commands.sh b/tests/commands.sh index 3af675962a..3febcbc632 100644 --- a/tests/commands.sh +++ b/tests/commands.sh @@ -47,6 +47,7 @@ TS_HELPER_PARTITIONS="${ts_helpersdir}sample-partitions" TS_HELPER_PATHS="${ts_helpersdir}test_pathnames" TS_HELPER_SCRIPT="${ts_helpersdir}test_script" TS_HELPER_SIGRECEIVE="${ts_helpersdir}test_sigreceive" +TS_HELPER_SIGSTATE="${ts_helpersdir}test_sigstate" TS_HELPER_STRERROR="${ts_helpersdir}test_strerror" TS_HELPER_STRUTILS="${ts_helpersdir}test_strutils" TS_HELPER_SYSINFO="${ts_helpersdir}test_sysinfo" diff --git a/tests/expected/kill/decode b/tests/expected/kill/decode new file mode 100644 index 0000000000..74783ad852 --- /dev/null +++ b/tests/expected/kill/decode @@ -0,0 +1,20 @@ +decode "0x00000000000044aa": +INT +ILL +ABRT +FPE +SEGV +TERM +decode "0x0000000000003015": +HUP +QUIT +TRAP +PIPE +ALRM +decode "0x0000000000000200": +USR1 +Pending (thread): INT ILL +Pending (process): USR1 +Blocked: INT ILL ABRT FPE USR1 SEGV TERM +Ignored: HUP QUIT TRAP PIPE ALRM +Caught: ILL USR1 diff --git a/tests/helpers/Makemodule.am b/tests/helpers/Makemodule.am index 67a1d3d096..fac8608cd2 100644 --- a/tests/helpers/Makemodule.am +++ b/tests/helpers/Makemodule.am @@ -24,6 +24,10 @@ check_PROGRAMS += test_sigreceive test_sigreceive_SOURCES = tests/helpers/test_sigreceive.c test_sigreceive_LDADD = $(LDADD) libcommon.la +check_PROGRAMS += test_sigstate +test_sigstate_SOURCES = tests/helpers/test_sigstate.c +test_sigstate_LDADD = $(LDADD) libcommon.la + check_PROGRAMS += test_tiocsti test_tiocsti_SOURCES = tests/helpers/test_tiocsti.c diff --git a/tests/helpers/test_sigstate.c b/tests/helpers/test_sigstate.c new file mode 100644 index 0000000000..52c7dcb723 --- /dev/null +++ b/tests/helpers/test_sigstate.c @@ -0,0 +1,94 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * test_sigstate - ... + * + * Written by Masatake YAMATO + */ + +#include "c.h" + +#include +#include +#include +#include +#include + +#define _U_ __attribute__((__unused__)) + +static enum { + HANDLER_NONE, + HANDLER_WRITE, + HANDLER_READ +} handler_state = HANDLER_NONE; + +static int ERRNO; + +static void handler(int signum _U_) +{ + char c; + + if (write(1, "USR1\n", 5) == -1) { + handler_state = HANDLER_WRITE; + goto out; + } + + if (read(0, &c, 1) != -1) + _exit(0); + handler_state = HANDLER_READ; + + out: + ERRNO = errno; +} + +int main(int argc _U_, char **argv _U_) +{ + sigset_t block_set; + + sigemptyset(&block_set); + sigaddset(&block_set, SIGINT); + sigaddset(&block_set, SIGILL); + sigaddset(&block_set, SIGABRT); + sigaddset(&block_set, SIGFPE); + sigaddset(&block_set, SIGSEGV); + sigaddset(&block_set, SIGTERM); + + if (sigprocmask(SIG_SETMASK, &block_set, NULL) == -1) + err(EXIT_FAILURE, "failed to mask signals"); + + raise(SIGINT); + raise(SIGILL); + +#define sigignore(S) if (signal(S, SIG_IGN) == SIG_ERR) \ + err(EXIT_FAILURE, "failed to make " #S "ignored") + + sigignore(SIGHUP); + sigignore(SIGQUIT); + sigignore(SIGTRAP); + sigignore(SIGPIPE); + sigignore(SIGALRM); + + signal(SIGBUS, SIG_DFL); + signal(SIGFPE, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + signal(32, SIG_DFL); + signal(33, SIG_DFL); + + if (signal(SIGUSR1, handler) == SIG_ERR) + err(EXIT_FAILURE, "failed to set a signal handler for SIGUSR1"); + if (signal(SIGILL, handler) == SIG_ERR) + err(EXIT_FAILURE, "failed to set a signal handler for SIGILL"); + + printf("%d\n", getpid()); + if (fflush(stdout) == EOF) + err(EXIT_FAILURE, "failed to flush stdout"); + + pause(); + if (ERRNO == 0) + errx(EXIT_FAILURE, "caught an unexpected signal"); + errno = ERRNO; + errx(EXIT_FAILURE, "failed in %s an ack from the command invoker", + handler_state == HANDLER_WRITE? "writing": "reading"); + + return 0; /* UNREACHABLE */ +} diff --git a/tests/ts/kill/decode b/tests/ts/kill/decode new file mode 100755 index 0000000000..03bc25ff60 --- /dev/null +++ b/tests/ts/kill/decode @@ -0,0 +1,69 @@ +#!/bin/bash + +# This file is part of util-linux. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +TS_TOPDIR="${0%/*}/../.." +TS_DESC="decode functions" + +. "$TS_TOPDIR/functions.sh" +ts_init "$*" + +ts_skip_qemu_user + +ts_check_test_command "$TS_CMD_KILL" +ts_check_test_command "$TS_HELPER_SIGSTATE" + +. "$TS_SELF/kill_functions.sh" + +decode() +{ + echo decode "\"$1\":" + "$TS_CMD_KILL" -l "$1" +} + +PID= +ACK= +{ + for d in 0x00000000000044aa \ + 0x0000000000003015 \ + 0x0000000000000200; do + decode "$d" + done + + coproc SIGSTATE { "$TS_HELPER_SIGSTATE" ; } + if read -u ${SIGSTATE[0]} PID; then + "$TS_CMD_KILL" -USR1 "$PID" + if read -u ${SIGSTATE[0]} ACK; then + # The taget process is in its signal handler for USR1. + # Sending one more USR1 is for making the signal pending state. + "$TS_CMD_KILL" -USR1 "$PID" + "$TS_CMD_KILL" -d "$PID" | { + if [[ $("$TS_CMD_KILL" --list=34) == RT0 ]]; then + # See man signal(7). + # The Linux kernel supports a range of 33 different real-time signals, + # numbered 32 to 64. However, the glibc POSIX threads implementation in‐ + # ternally uses two (for NPTL) or three (for LinuxThreads) real-time sig‐ + # nals (see pthreads(7)), and adjusts the value of SIGRTMIN suitably (to + # 34 or 35). + sed -e s/' 32 33'// -e s/' 34'// + else + cat + fi + } + fi + echo DONE >&"${SIGSTATE[1]}" + fi + wait ${SIGSTATE_PID} +} > "$TS_OUTPUT" 2>&1 + +ts_finalize -- 2.47.2