summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--doc/strace.1.in5
-rw-r--r--src/filter_qualify.c1
-rw-r--r--src/number_set.h1
-rw-r--r--src/strace.c3
-rw-r--r--src/util.c44
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/gen_tests.in3
-rwxr-xr-xtests/pure_executables.list1
-rw-r--r--tests/signalfd4-yy.c4
-rw-r--r--tests/signalfd4.c35
11 files changed, 93 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index c7798adf0..c82e6c895 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,8 @@ Noteworthy changes in release ?.? (????-??-??)
==============================================
* Improvements
+ * Implemented --decode-fds=signalfd option for decoding of signal masks
+ associated with signalfd file descriptors.
* Implemented -e trace-fds=set option for filtering only the syscalls
that operate on the specified set of file descriptors.
* Implemented -l/--syscall-limit option to automatically detach tracees
diff --git a/doc/strace.1.in b/doc/strace.1.in
index 16a94fc7d..8a8137bad 100644
--- a/doc/strace.1.in
+++ b/doc/strace.1.in
@@ -919,7 +919,7 @@ Decode various information associated with file descriptors. The default is
.I set
can include the following elements:
.RS
-.TP 8
+.TP 9
.B path
Print file paths.
Also enables printing of tracee's current working directory when
@@ -934,6 +934,9 @@ Print character/block device numbers.
.TQ
.B pidfd
Print PIDs associated with pidfd file descriptors.
+.TQ
+.B signalfd
+Print signal masks associated with signalfd file descriptors.
.RE
.TP
\fB\-e\ decode\-pids\fR=\,\fIset\fR
diff --git a/src/filter_qualify.c b/src/filter_qualify.c
index 3aa9f2a19..9d23b6a11 100644
--- a/src/filter_qualify.c
+++ b/src/filter_qualify.c
@@ -106,6 +106,7 @@ decode_fd_str_to_uint(const char *str)
{ DECODE_FD_SOCKET, "socket" },
{ DECODE_FD_DEV, "dev" },
{ DECODE_FD_PIDFD, "pidfd" },
+ { DECODE_FD_SIGNALFD, "signalfd" },
};
return (int) find_arg_val(str, decode_fd_strs, -1ULL, -1ULL);
diff --git a/src/number_set.h b/src/number_set.h
index 639d4c256..2458fdef7 100644
--- a/src/number_set.h
+++ b/src/number_set.h
@@ -76,6 +76,7 @@ enum decode_fd_bits {
DECODE_FD_SOCKET,
DECODE_FD_DEV,
DECODE_FD_PIDFD,
+ DECODE_FD_SIGNALFD,
NUM_DECODE_FD_BITS
};
diff --git a/src/strace.c b/src/strace.c
index 0f34e8961..7caa6d9ec 100644
--- a/src/strace.c
+++ b/src/strace.c
@@ -369,7 +369,8 @@ Output format:\n\
details: dev (device major/minor for block/char device files)\n\
path (file path),\n\
pidfd (associated PID for pidfds),\n\
- socket (protocol-specific information for socket descriptors)\n\
+ socket (protocol-specific information for socket descriptors),\n\
+ signalfd (signal masks for signalfds)\n\
"
#ifdef ENABLE_SECONTEXT
"\
diff --git a/src/util.c b/src/util.c
index e43e4b725..343cf8850 100644
--- a/src/util.c
+++ b/src/util.c
@@ -790,6 +790,47 @@ printpidfd(pid_t pid_of_fd, int fd, const char *path)
return true;
}
+static bool
+print_fdinfo_sigmask(const char *value, void *data)
+{
+#ifdef WORDS_BIGENDIAN
+ unsigned int pos_xor_mask = current_wordsize - 1;
+#else
+ unsigned int pos_xor_mask = 0;
+#endif
+ size_t sigset_size = strlen(value) / 2;
+ uint8_t *sigmask = xmalloc(sigset_size);
+
+ for (size_t i = 0; i < sigset_size; ++i) {
+ uint8_t byte;
+ if (sscanf(value + i * 2, "%02hhx", &byte) != 1) {
+ free(sigmask);
+ return false;
+ }
+ sigmask[(sigset_size - 1 - i) ^ pos_xor_mask] = byte;
+ }
+
+ tprint_associated_info_begin();
+ tprints_string(sprintsigmask_n("signalfd:", sigmask, sigset_size));
+ tprint_associated_info_end();
+
+ free(sigmask);
+ return true;
+}
+
+static bool
+printsignalfd(pid_t pid_of_fd, int fd, const char *path)
+{
+ static const char signalfd_path[] = "anon_inode:[signalfd]";
+ static const char sigmask_pfx[] = "sigmask:\t";
+
+ if (strcmp(path, signalfd_path))
+ return false;
+
+ return scan_fdinfo(pid_of_fd, fd, sigmask_pfx, sizeof(sigmask_pfx) - 1,
+ print_fdinfo_sigmask, NULL);
+}
+
static void
print_quoted_string_in_angle_brackets(const char *str, const bool deleted)
{
@@ -821,6 +862,9 @@ printfd_pid_with_finfo(struct tcb *tcp, pid_t pid, int fd, const struct finfo *f
if (is_number_in_set(DECODE_FD_PIDFD, decode_fd_set) &&
printpidfd(pid, fd, path))
goto printed;
+ if (is_number_in_set(DECODE_FD_SIGNALFD, decode_fd_set) &&
+ printsignalfd(pid, fd, path))
+ goto printed;
if (is_number_in_set(DECODE_FD_PATH, decode_fd_set))
print_quoted_string_in_angle_brackets(path,
finfo? finfo->deleted: deleted);
diff --git a/tests/.gitignore b/tests/.gitignore
index 4c753e324..d0f99f01e 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -982,6 +982,7 @@ signal
signal_receive
signal_receive--pidns-translation
signalfd4
+signalfd4-yy
sigpending
sigprocmask
sigreturn
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index 1316ad6e8..f19963b06 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -960,7 +960,8 @@ siginfo -e trace=none
signal -a25 -e signal=none -e trace='/^signal$'
signal_receive -a16 -e trace=kill
signal_receive--pidns-translation test_pidns -a16 -e trace=kill
-signalfd4
+signalfd4 -a32
+signalfd4-yy --trace=signalfd4 -yy
sigpending -a15
sigprocmask -a34
sigreturn -esignal='!USR1'
diff --git a/tests/pure_executables.list b/tests/pure_executables.list
index a1315f64e..4c32d8b99 100755
--- a/tests/pure_executables.list
+++ b/tests/pure_executables.list
@@ -695,6 +695,7 @@ sigaltstack
siginfo
signal
signalfd4
+signalfd4-yy
sigpending
sigprocmask
sigreturn
diff --git a/tests/signalfd4-yy.c b/tests/signalfd4-yy.c
new file mode 100644
index 000000000..6a5262628
--- /dev/null
+++ b/tests/signalfd4-yy.c
@@ -0,0 +1,4 @@
+#define SKIP_IF_PROC_IS_UNAVAILABLE skip_if_unavailable("/proc/self/fd/")
+#define PRINT_SIGNALFD
+
+#include "signalfd4.c"
diff --git a/tests/signalfd4.c b/tests/signalfd4.c
index e45e9425c..97e7977a2 100644
--- a/tests/signalfd4.c
+++ b/tests/signalfd4.c
@@ -20,20 +20,47 @@
# include <sys/signalfd.h>
# include "kernel_fcntl.h"
+#ifndef SKIP_IF_PROC_IS_UNAVAILABLE
+# define SKIP_IF_PROC_IS_UNAVAILABLE
+#endif
+
int
main(void)
{
- const char *const sigs = SIGUSR2 < SIGCHLD ? "USR2 CHLD" : "CHLD USR2";
+ SKIP_IF_PROC_IS_UNAVAILABLE;
+
+ const char *const sigs1 = "USR2";
+ const char *const sigs2 = SIGUSR2 < SIGCHLD ? "USR2 CHLD" : "CHLD USR2";
const unsigned int size = get_sigset_size();
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGUSR2);
+
+ int fd = signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
+
+#ifdef PRINT_SIGNALFD
+ if (fd == -1)
+ perror_msg_and_skip("signalfd");
+#endif
+
+ printf("signalfd4(-1, [%s], %u, SFD_CLOEXEC|SFD_NONBLOCK) = %s",
+ sigs1, size, sprintrc(fd));
+#ifdef PRINT_SIGNALFD
+ printf("<signalfd:[%s]>\n", sigs1);
+#else
+ putchar('\n');
+#endif
+
sigaddset(&mask, SIGCHLD);
+ fd = signalfd(fd, &mask, 0);
- int fd = signalfd(-1, &mask, O_CLOEXEC | O_NONBLOCK);
- printf("signalfd4(-1, [%s], %u, SFD_CLOEXEC|SFD_NONBLOCK) = %s\n",
- sigs, size, sprintrc(fd));
+#ifdef PRINT_SIGNALFD
+ printf("signalfd4(%d<signalfd:[%s]>, [%s], %u, 0) = %s<signalfd:[%s]>\n",
+ fd, sigs1, sigs2, size, sprintrc(fd), sigs2);
+#else
+ printf("signalfd4(%d, [%s], %u, 0) = %s\n", fd, sigs2, size, sprintrc(fd));
+#endif
puts("+++ exited with 0 +++");
return 0;