diff options
-rw-r--r-- | gdb/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/Makefile.in | 1 | ||||
-rw-r--r-- | gdb/unittests/scoped_ignore_signal-selftests.c | 126 |
3 files changed, 133 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a56531e..e4e5817 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,11 @@ 2021-06-17 Pedro Alves <pedro@palves.net> + * Makefile.in (SELFTESTS_SRCS): Add + unittests/scoped_ignore_signal-selftests.c. + * unittests/scoped_ignore_signal-selftests.c: New. + +2021-06-17 Pedro Alves <pedro@palves.net> + * gdbsupport/scoped_ignore_signal.h: New. * compile/compile.c: Include gdbsupport/scoped_ignore_signal.h instead of <signal.h>. Don't include <unistd.h>. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 881ebde..1bc9788 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -461,6 +461,7 @@ SELFTESTS_SRCS = \ unittests/mkdir-recursive-selftests.c \ unittests/rsp-low-selftests.c \ unittests/scoped_fd-selftests.c \ + unittests/scoped_ignore_signal-selftests.c \ unittests/scoped_mmap-selftests.c \ unittests/scoped_restore-selftests.c \ unittests/search-memory-selftests.c \ diff --git a/gdb/unittests/scoped_ignore_signal-selftests.c b/gdb/unittests/scoped_ignore_signal-selftests.c new file mode 100644 index 0000000..29826e3 --- /dev/null +++ b/gdb/unittests/scoped_ignore_signal-selftests.c @@ -0,0 +1,126 @@ +/* Self tests for scoped_ignored_signal for GDB, the GNU debugger. + + Copyright (C) 2021 Free Software Foundation, Inc. + + This file is part of GDB. + + This program 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 3 of the License, or + (at your option) any later version. + + This program 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "gdbsupport/scoped_ignore_signal.h" +#include "gdbsupport/selftest.h" +#include "gdbsupport/scope-exit.h" +#include <unistd.h> +#include <signal.h> + +namespace selftests { +namespace scoped_ignore_sig { + +#ifdef SIGPIPE + +/* True if the SIGPIPE handler ran. */ +static volatile sig_atomic_t got_sigpipe = 0; + +/* SIGPIPE handler for testing. */ + +static void +handle_sigpipe (int) +{ + got_sigpipe = 1; +} + +/* Test scoped_ignore_sigpipe. */ + +static void +test_sigpipe () +{ + auto *osig = signal (SIGPIPE, handle_sigpipe); + SCOPE_EXIT { signal (SIGPIPE, osig); }; + +#ifdef HAVE_SIGPROCMASK + /* Make sure SIGPIPE isn't blocked. */ + sigset_t set, old_state; + sigemptyset (&set); + sigaddset (&set, SIGPIPE); + sigprocmask (SIG_UNBLOCK, &set, &old_state); + SCOPE_EXIT { sigprocmask (SIG_SETMASK, &old_state, nullptr); }; +#endif + + /* Create pipe, and close read end so that writes to the pipe fail + with EPIPE. */ + + int fd[2]; + char c = 0xff; + int r; + + r = pipe (fd); + SELF_CHECK (r == 0); + + close (fd[0]); + SCOPE_EXIT { close (fd[1]); }; + + /* Check that writing to the pipe results in EPIPE. EXPECT_SIG + indicates whether a SIGPIPE signal is expected. */ + auto check_pipe_write = [&] (bool expect_sig) + { + got_sigpipe = 0; + errno = 0; + + r = write (fd[1], &c, 1); + SELF_CHECK (r == -1 && errno == EPIPE + && got_sigpipe == expect_sig); + }; + + /* Check that without a scoped_ignore_sigpipe in scope we indeed get + a SIGPIPE signal. */ + check_pipe_write (true); + + /* Now check that with a scoped_ignore_sigpipe in scope, SIGPIPE is + ignored/blocked. */ + { + scoped_ignore_sigpipe ignore1; + + check_pipe_write (false); + + /* Check that scoped_ignore_sigpipe nests correctly. */ + { + scoped_ignore_sigpipe ignore2; + + check_pipe_write (false); + } + + /* If nesting works correctly, this write results in no + SIGPIPE. */ + check_pipe_write (false); + } + + /* No scoped_ignore_sigpipe is in scope anymore, so this should + result in a SIGPIPE signal. */ + check_pipe_write (true); +} + +#endif /* SIGPIPE */ + +} /* namespace scoped_ignore_sig */ +} /* namespace selftests */ + +void _initialize_scoped_ignore_signal_selftests (); +void +_initialize_scoped_ignore_signal_selftests () +{ +#ifdef SIGPIPE + selftests::register_test ("scoped_ignore_sigpipe", + selftests::scoped_ignore_sig::test_sigpipe); +#endif +} |