From: Dmitry V. Levin Date: Fri, 10 Jun 2016 09:16:10 +0000 (+0000) Subject: tests: extend test coverage of waitid syscall X-Git-Tag: v4.13~154 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=176c568a6a95d6742bab60a62bbfb54cb46dbd52;p=strace tests: extend test coverage of waitid syscall * tests/waitid.c: New file. * tests/waitid-v.c: Likewise. * tests/waitid.test: New test. * tests/waitid-v.test: Likewise. * tests/.gitignore: Add waitid and waitid-v. * tests/Makefile.am (check_PROGRAMS): Likewise. (DECODER_TESTS): Add waitid.test and waitid-v.test. --- diff --git a/tests/.gitignore b/tests/.gitignore index 3ee848d2..65f3c060 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -278,6 +278,8 @@ vmsplice wait wait4 wait4-v +waitid +waitid-v waitpid xattr xet_robust_list diff --git a/tests/Makefile.am b/tests/Makefile.am index 2efe44c5..48e44011 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -331,6 +331,8 @@ check_PROGRAMS = \ wait \ wait4 \ wait4-v \ + waitid \ + waitid-v \ waitpid \ xattr \ xet_robust_list \ @@ -630,6 +632,8 @@ DECODER_TESTS = \ wait.test \ wait4.test \ wait4-v.test \ + waitid.test \ + waitid-v.test \ waitpid.test \ xattr.test \ xet_robust_list.test \ diff --git a/tests/waitid-v.c b/tests/waitid-v.c new file mode 100644 index 00000000..06171ae1 --- /dev/null +++ b/tests/waitid-v.c @@ -0,0 +1,3 @@ +/* This file is part of waitid-v strace test. */ +#define VERBOSE_RUSAGE +#include "waitid.c" diff --git a/tests/waitid-v.test b/tests/waitid-v.test new file mode 100755 index 00000000..eb498cb0 --- /dev/null +++ b/tests/waitid-v.test @@ -0,0 +1,6 @@ +#!/bin/sh + +# Check verbose decoding of waitid syscall. + +. "${srcdir=.}/init.sh" +run_strace_match_diff -v -e signal=none -e trace=waitid diff --git a/tests/waitid.c b/tests/waitid.c new file mode 100644 index 00000000..bd7e8efb --- /dev/null +++ b/tests/waitid.c @@ -0,0 +1,263 @@ +/* + * Check decoding of waitid syscall. + * + * Copyright (c) 2015-2016 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tests.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static const char * +sprint_rusage(const struct rusage *const ru) +{ + static char buf[1024]; + snprintf(buf, sizeof(buf), + "{ru_utime={%llu, %llu}" + ", ru_stime={%llu, %llu}" +#ifdef VERBOSE_RUSAGE + ", ru_maxrss=%llu" + ", ru_ixrss=%llu" + ", ru_idrss=%llu" + ", ru_isrss=%llu" + ", ru_minflt=%llu" + ", ru_majflt=%llu" + ", ru_nswap=%llu" + ", ru_inblock=%llu" + ", ru_oublock=%llu" + ", ru_msgsnd=%llu" + ", ru_msgrcv=%llu" + ", ru_nsignals=%llu" + ", ru_nvcsw=%llu" + ", ru_nivcsw=%llu}" +#else + ", ...}" +#endif + , widen_to_ull(ru->ru_utime.tv_sec) + , widen_to_ull(ru->ru_utime.tv_usec) + , widen_to_ull(ru->ru_stime.tv_sec) + , widen_to_ull(ru->ru_stime.tv_usec) +#ifdef VERBOSE_RUSAGE + , widen_to_ull(ru->ru_maxrss) + , widen_to_ull(ru->ru_ixrss) + , widen_to_ull(ru->ru_idrss) + , widen_to_ull(ru->ru_isrss) + , widen_to_ull(ru->ru_minflt) + , widen_to_ull(ru->ru_majflt) + , widen_to_ull(ru->ru_nswap) + , widen_to_ull(ru->ru_inblock) + , widen_to_ull(ru->ru_oublock) + , widen_to_ull(ru->ru_msgsnd) + , widen_to_ull(ru->ru_msgrcv) + , widen_to_ull(ru->ru_nsignals) + , widen_to_ull(ru->ru_nvcsw) + , widen_to_ull(ru->ru_nivcsw) +#endif + ); + return buf; +} + +#define CASE(x) case x: return #x + +static const char * +si_code_2_name(const int code) +{ + switch (code) { +#ifdef CLD_EXITED + CASE(CLD_EXITED); +#endif +#ifdef CLD_KILLED + CASE(CLD_KILLED); +#endif +#ifdef CLD_DUMPED + CASE(CLD_DUMPED); +#endif +#ifdef CLD_TRAPPED + CASE(CLD_TRAPPED); +#endif +#ifdef CLD_STOPPED + CASE(CLD_STOPPED); +#endif +#ifdef CLD_CONTINUED + CASE(CLD_CONTINUED); +#endif + default: perror_msg_and_fail("unknown si_code %d", code); + } +} + +static const char * +sprint_siginfo(const siginfo_t *const si, const char *const status_text) +{ + static char buf[1024]; + snprintf(buf, sizeof(buf), + "{si_signo=SIGCHLD" + ", si_code=%s" + ", si_pid=%u" + ", si_uid=%u" + ", si_status=%s" + ", si_utime=%llu" + ", si_stime=%llu}", + si_code_2_name(si->si_code), + si->si_pid, + si->si_uid, + status_text, + widen_to_ull(si->si_utime), + widen_to_ull(si->si_stime)); + return buf; +} + +static unsigned long +poison(unsigned int v) +{ + return (unsigned long) 0xfacefeed00000000 | v; +} + +static long +do_waitid(const unsigned int idtype, + const unsigned int id, + const siginfo_t const *infop, + const unsigned int options, + const struct rusage *const rusage) +{ + sigset_t mask = {}; + sigaddset(&mask, SIGCHLD); + + assert(sigprocmask(SIG_BLOCK, &mask, NULL) == 0); + long rc = syscall(__NR_waitid, poison(idtype), poison(id), + infop, poison(options), rusage); + assert(sigprocmask(SIG_UNBLOCK, &mask, NULL) == 0); + return rc; +} + +int +main(void) +{ + tprintf("%s", ""); + + int fds[2]; + if (pipe(fds)) + perror_msg_and_fail("pipe"); + + pid_t pid; + pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + char c; + (void) close(1); + assert(read(0, &c, sizeof(c)) == 1); + return 42; + } + + (void) close(0); + + if (do_waitid(P_PID, pid, 0, WNOHANG|WEXITED, 0)) + perror_msg_and_fail("waitid #1"); + tprintf("waitid(P_PID, %d, NULL, WNOHANG|WEXITED, NULL) = 0\n", pid); + + siginfo_t *const sinfo = tail_alloc(sizeof(*sinfo)); + memset(sinfo, 0, sizeof(*sinfo)); + struct rusage *const rusage = tail_alloc(sizeof(*rusage)); + if (do_waitid(P_PID, pid, sinfo, WNOHANG|WEXITED|WSTOPPED, rusage)) + perror_msg_and_fail("waitid #2"); + tprintf("waitid(P_PID, %d, {}, WNOHANG|WEXITED|WSTOPPED, %s) = 0\n", + pid, sprint_rusage(rusage)); + + assert(write(1, "", 1) == 1); + (void) close(1); + + if (do_waitid(P_PID, pid, sinfo, WEXITED, rusage)) + perror_msg_and_fail("waitid #3"); + tprintf("waitid(P_PID, %d, %s, WEXITED, %s) = 0\n", + pid, sprint_siginfo(sinfo, "42"), sprint_rusage(rusage)); + + pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + (void) raise(SIGUSR1); + return 1; + } + + if (do_waitid(P_PID, pid, sinfo, WEXITED, rusage)) + perror_msg_and_fail("waitid #4"); + tprintf("waitid(P_PID, %d, %s, WEXITED, %s) = 0\n", + pid, sprint_siginfo(sinfo, "SIGUSR1"), sprint_rusage(rusage)); + + if (pipe(fds)) + perror_msg_and_fail("pipe"); + pid = fork(); + if (pid < 0) + perror_msg_and_fail("fork"); + + if (!pid) { + (void) close(1); + raise(SIGSTOP); + char c; + assert(read(0, &c, sizeof(c)) == 1); + return 0; + } + + (void) close(0); + + if (do_waitid(P_PID, pid, sinfo, WSTOPPED, rusage)) + perror_msg_and_fail("waitid #5"); + tprintf("waitid(P_PID, %d, %s, WSTOPPED, %s) = 0\n", + pid, sprint_siginfo(sinfo, "SIGSTOP"), sprint_rusage(rusage)); + + if (kill(pid, SIGCONT)) + perror_msg_and_fail("kill(SIGCONT)"); + +#if defined WCONTINUED + if (do_waitid(P_PID, pid, sinfo, WCONTINUED, rusage)) + perror_msg_and_fail("waitid #6"); + tprintf("waitid(P_PID, %d, %s, WCONTINUED, %s) = 0\n", + pid, sprint_siginfo(sinfo, "SIGCONT"), sprint_rusage(rusage)); +#endif /* WCONTINUED */ + + assert(write(1, "", 1) == 1); + (void) close(1); + + if (do_waitid(P_PID, pid, sinfo, WEXITED, rusage)) + perror_msg_and_fail("waitid #7"); + tprintf("waitid(P_PID, %d, %s, WEXITED, %s) = 0\n", + pid, sprint_siginfo(sinfo, "0"), sprint_rusage(rusage)); + + long rc = do_waitid(P_ALL, -1, sinfo, WEXITED|WSTOPPED, rusage); + tprintf("waitid(P_ALL, -1, %p, WEXITED|WSTOPPED, %p)" + " = %ld %s (%m)\n", sinfo, rusage, rc, errno2name()); + + tprintf("%s\n", "+++ exited with 0 +++"); + return 0; +} diff --git a/tests/waitid.test b/tests/waitid.test new file mode 100755 index 00000000..3bcba3ab --- /dev/null +++ b/tests/waitid.test @@ -0,0 +1,6 @@ +#!/bin/sh + +# Check decoding of waitid syscall. + +. "${srcdir=.}/init.sh" +run_strace_match_diff -esignal=none