From patchwork Wed Nov 20 14:15:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 179854 Delivered-To: patch@linaro.org Received: by 2002:a92:38d5:0:0:0:0:0 with SMTP id g82csp2162985ilf; Wed, 20 Nov 2019 06:16:20 -0800 (PST) X-Google-Smtp-Source: APXvYqy44OTSrPOumFKaOJ+MJjd/y7dmoyM17yQ6dw2L0udDyyyQW+PKh+S4ab0RRmtXEecsnwqc X-Received: by 2002:a19:ca03:: with SMTP id a3mr3178028lfg.20.1574259379399; Wed, 20 Nov 2019 06:16:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574259379; cv=none; d=google.com; s=arc-20160816; b=DwN2NSpQh+cSe9cqZEQc3ajpYD8h1QpKhSiyn5fbk0zvMNjLIXuuNe/me9JoZ0vrUt RhkdbhXmlUGmG3TNT5dEF5Ft/CdBxbSM+2fvzxQ2l50hnw5+jYZ4/L3b+QBFQQiScC7a grbrASLbay0FnTZR4vr6sS6QmvW21GyYdDV57n6TlhTVtQDUuYk5EN8emkEEJOR2Gl4X b9Mt+pPkfwoVZDXPCK+kMN5ycD+Yjj4LdOWYgCqI9CzRDmlFZgbicIhAEjUJNnb1l81e YdfJ7Zo70fOZpZDcY9IhKjrgSB3eShflJ+OATfJTDgQhj3qQFIMwiP3jQOaVmvHvnYg9 fcDw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:to:from :dkim-signature:delivered-to:sender:list-help:list-post:list-archive :list-subscribe:list-unsubscribe:list-id:precedence:mailing-list :dkim-signature:domainkey-signature; bh=0DIElEKx93V53y5V4vttZ8xgf5LGpnf7T9X8fJpJPCg=; b=zIew+3fGFTS127SJVcizPHzErzCLE28hYDxj8yv1IFEZ3GcKPjgwaBR0a6EfSa2tTt p+g/E8DAsxF3frRfsG9BXE/7KFjLEIHPtKwWou6LNj/kCYgC+ja6Bo7J59VE1iQHrnHa 3X7a5QL+5jitnBC3Eg1W7ScwRkSHBJcBYnNerFnvjgtVUIdFiWYiu7pPZUYJ+nq5PXRs Ngd6T95Qqgpq+naKuL/FrdJ/bgFbRObDHx3Lwi+3kqCw6xmumSZif3lriM9nh6PYbHlK TkVrgTvl0DU7nWvNj/A6oZqcaydumlGGHde6f7ZB0TgyQ2zdAhxIpJtEm3Wf9RK1MuI/ uenw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=p3OpyEEX; dkim=pass header.i=@linaro.org header.s=google header.b=DwEIsh31; spf=pass (google.com: domain of libc-alpha-return-107210-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="libc-alpha-return-107210-patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id t52si18567073edd.3.2019.11.20.06.16.18 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 20 Nov 2019 06:16:19 -0800 (PST) Received-SPF: pass (google.com: domain of libc-alpha-return-107210-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=p3OpyEEX; dkim=pass header.i=@linaro.org header.s=google header.b=DwEIsh31; spf=pass (google.com: domain of libc-alpha-return-107210-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="libc-alpha-return-107210-patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:in-reply-to :references; q=dns; s=default; b=KZ2lZM2QrRt6C9Z6XF8SU5r814CO6/R PlM51MDSqgKRxWxgV486wjHNWYZMkLenYMZQmpQ/smMjeDTbmZOOv3k3JA7Hicpm 0CJW+7SreqQKPCH5iCXLaZBToObZYyeZC1aFeIkQwYfBIXlY2Rn3B1CAzr1Bb6Qa 8uhOu0606Aqw= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:in-reply-to :references; s=default; bh=5JxHQroGabelCFX4dWTsIT3AawA=; b=p3Opy EEXxWy1J6ScLkdLAPSmJM2Ykngum3eHe6dWmWmxQrDkvheXzvXscxy1Xy0ymzm6o rKPSoFoFahMejOQnxLPDQYshgDQoZkYPkgblHpnGbf6j4rTjsNIsX7/o98vIx3D2 MEj8Ypsw5s5R5dtmcD7MJTSwQfjur/5WbL92j8= Received: (qmail 20168 invoked by alias); 20 Nov 2019 14:15:47 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 20093 invoked by uid 89); 20 Nov 2019 14:15:47 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=him, his, act X-HELO: mail-qt1-f194.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:subject:date:message-id:in-reply-to:references; bh=0DIElEKx93V53y5V4vttZ8xgf5LGpnf7T9X8fJpJPCg=; b=DwEIsh31GbywVB91vhwAx06fNbdAB4hhzSk6Qbl6BzXtgs/S6UUdxporVLsBjIPzV5 Wnh/K3SUzwTAFfyqS8+L4SRLS+dFMN2Qr/imqsawtO1MQ2XEWzRoTcX1WxOHfxySOxSg 34SPYbQTVFxqfrYB399P7/s40qoElLCSLFXKPHyV5G2ZemmuDikLFg/eTl/q/tbrJocM fKBJ+OUipyCIcpl0u+Nfcp1dKsz+O3Cpd4Rp9hx0OAMCMO5F4QGA1EnNTFilrcUOc1wX 0M6EgbuFuh/p6LpGNlLb9khuF3srV6v5S7D6cuKEJzBjxx3Lg9+Rr62iPtts1quEuAT1 TygA== Return-Path: From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH 2/3] posix: Refactor tst-waitid Date: Wed, 20 Nov 2019 11:15:34 -0300 Message-Id: <20191120141535.5303-2-adhemerval.zanella@linaro.org> In-Reply-To: <20191120141535.5303-1-adhemerval.zanella@linaro.org> References: <20191120141535.5303-1-adhemerval.zanella@linaro.org> The main changes are: - Adapt to libsupport. - Synchronize the signal handler using atomics. - Replace waitpid by waitid calls. - Use support_process_state_wait to wait for child state. - Add tests for P_PGID and P_ALL. Checked on x86_64-linux-gnu and i686-linux-gnu. --- posix/tst-waitid.c | 519 +++++++++++++-------------------------------- 1 file changed, 153 insertions(+), 366 deletions(-) -- 2.17.1 diff --git a/posix/tst-waitid.c b/posix/tst-waitid.c index c82ec2b566..1134d92bb3 100644 --- a/posix/tst-waitid.c +++ b/posix/tst-waitid.c @@ -22,13 +22,20 @@ #include #include #include +#include +#include +#include + +#include +#include +#include +#include static void -test_child (void) +test_child (bool setgroup) { - /* Wait a second to be sure the parent set his variables before we - produce a SIGCHLD. */ - sleep (1); + if (setgroup) + TEST_COMPARE (setpgid (0, 0), 0); /* First thing, we stop ourselves. */ raise (SIGSTOP); @@ -44,20 +51,16 @@ test_child (void) # define WSTOPPED WUNTRACED #endif -static sig_atomic_t expecting_sigchld, spurious_sigchld; +static atomic_int expecting_sigchld, spurious_sigchld; #ifdef SA_SIGINFO static siginfo_t sigchld_info; static void sigchld (int signo, siginfo_t *info, void *ctx) { - if (signo != SIGCHLD) - { - printf ("SIGCHLD handler got signal %d instead!\n", signo); - _exit (EXIT_FAILURE); - } + TEST_COMPARE (signo, SIGCHLD); - if (! expecting_sigchld) + if (expecting_sigchld == 0) { spurious_sigchld = 1; printf ("spurious SIGCHLD: signo %d code %d status %d pid %d\n", @@ -69,154 +72,66 @@ sigchld (int signo, siginfo_t *info, void *ctx) expecting_sigchld = 0; } } +#endif static void -check_sigchld (const char *phase, int *ok, int code, int status, pid_t pid) +check_sigchld (int code, int status, pid_t pid) { - if (expecting_sigchld) - { - printf ("missing SIGCHLD on %s\n", phase); - *ok = EXIT_FAILURE; - expecting_sigchld = 0; - return; - } - - if (sigchld_info.si_signo != SIGCHLD) - { - printf ("SIGCHLD for %s signal %d\n", phase, sigchld_info.si_signo); - *ok = EXIT_FAILURE; - } - if (sigchld_info.si_code != code) - { - printf ("SIGCHLD for %s code %d\n", phase, sigchld_info.si_code); - *ok = EXIT_FAILURE; - } - if (sigchld_info.si_status != status) - { - printf ("SIGCHLD for %s status %d\n", phase, sigchld_info.si_status); - *ok = EXIT_FAILURE; - } - if (sigchld_info.si_pid != pid) - { - printf ("SIGCHLD for %s pid %d\n", phase, sigchld_info.si_pid); - *ok = EXIT_FAILURE; - } -} -# define CHECK_SIGCHLD(phase, code_check, status_check) \ - check_sigchld ((phase), &status, (code_check), (status_check), pid) -#else -# define CHECK_SIGCHLD(phase, code, status) ((void) 0) +#ifdef SA_SIGINFO + TEST_COMPARE (expecting_sigchld, 0); + TEST_COMPARE (sigchld_info.si_signo, SIGCHLD); + TEST_COMPARE (sigchld_info.si_code, code); + TEST_COMPARE (sigchld_info.si_status, status); + TEST_COMPARE (sigchld_info.si_pid, pid); #endif +} static int -do_test (int argc, char *argv[]) +do_test_waitd_common (idtype_t type, pid_t pid) { -#ifdef SA_SIGINFO - struct sigaction sa; - sa.sa_flags = SA_SIGINFO|SA_RESTART; - sa.sa_sigaction = &sigchld; - if (sigemptyset (&sa.sa_mask) < 0 || sigaction (SIGCHLD, &sa, NULL) < 0) - { - printf ("setting SIGCHLD handler: %m\n"); - return EXIT_FAILURE; - } -#endif - - expecting_sigchld = 1; - - pid_t pid = fork (); - if (pid < 0) - { - printf ("fork: %m\n"); - return EXIT_FAILURE; - } - else if (pid == 0) - { - test_child (); - _exit (127); - } + /* Adding process_state_tracing_stop ('t') allows the test to work under + trace programs such as ptrace. */ + enum process_state_t stop_state = process_state_stopped + | process_state_tracing_stop; - int status = EXIT_SUCCESS; -#define RETURN(ok) \ - do { if (status == EXIT_SUCCESS) status = (ok); goto out; } while (0) + support_process_state_wait (pid, stop_state); - /* Give the child a chance to stop. */ - sleep (3); + /* Wait the SIGCHLD handler to act. */ + while (expecting_sigchld == 1); - CHECK_SIGCHLD ("stopped (before waitid)", CLD_STOPPED, SIGSTOP); + check_sigchld (CLD_STOPPED, SIGSTOP, pid); /* Now try a wait that should not succeed. */ siginfo_t info; + int fail; + info.si_signo = 0; /* A successful call sets it to SIGCHLD. */ - int fail = waitid (P_PID, pid, &info, WEXITED|WCONTINUED|WNOHANG); - switch (fail) - { - default: - printf ("waitid returned bogus value %d\n", fail); - RETURN (EXIT_FAILURE); - case -1: - printf ("waitid WNOHANG on stopped: %m\n"); - RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); - case 0: - if (info.si_signo == 0) - break; - if (info.si_signo == SIGCHLD) - printf ("waitid WNOHANG on stopped status %d\n", info.si_status); - else - printf ("waitid WNOHANG on stopped signal %d\n", info.si_signo); - RETURN (EXIT_FAILURE); - } + fail = waitid (P_PID, pid, &info, WEXITED|WCONTINUED|WNOHANG); + if (fail == -1 && errno == ENOTSUP) + FAIL_RET ("waitid WNOHANG on stopped: %m"); + TEST_COMPARE (fail, 0); + TEST_COMPARE (info.si_signo, 0); /* Next the wait that should succeed right away. */ info.si_signo = 0; /* A successful call sets it to SIGCHLD. */ info.si_pid = -1; info.si_status = -1; fail = waitid (P_PID, pid, &info, WSTOPPED|WNOHANG); - switch (fail) - { - default: - printf ("waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail); - RETURN (EXIT_FAILURE); - case -1: - printf ("waitid WSTOPPED|WNOHANG on stopped: %m\n"); - RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); - case 0: - if (info.si_signo != SIGCHLD) - { - printf ("waitid WSTOPPED|WNOHANG on stopped signal %d\n", - info.si_signo); - RETURN (EXIT_FAILURE); - } - if (info.si_code != CLD_STOPPED) - { - printf ("waitid WSTOPPED|WNOHANG on stopped code %d\n", - info.si_code); - RETURN (EXIT_FAILURE); - } - if (info.si_status != SIGSTOP) - { - printf ("waitid WSTOPPED|WNOHANG on stopped status %d\n", - info.si_status); - RETURN (EXIT_FAILURE); - } - if (info.si_pid != pid) - { - printf ("waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n", - info.si_pid, pid); - RETURN (EXIT_FAILURE); - } - } + if (fail == -1 && errno == ENOTSUP) + FAIL_RET ("waitid WNOHANG on stopped: %m"); + TEST_COMPARE (fail, 0); + TEST_COMPARE (info.si_signo, SIGCHLD); + TEST_COMPARE (info.si_code, CLD_STOPPED); + TEST_COMPARE (info.si_status, SIGSTOP); + TEST_COMPARE (info.si_pid, pid); expecting_sigchld = WCONTINUED != 0; if (kill (pid, SIGCONT) != 0) - { - printf ("kill (%d, SIGCONT): %m\n", pid); - RETURN (EXIT_FAILURE); - } + FAIL_RET ("kill (%d, SIGCONT): %m\n", pid); /* Wait for the child to have continued. */ - sleep (2); + support_process_state_wait (pid, process_state_sleeping); #if WCONTINUED != 0 if (expecting_sigchld) @@ -224,152 +139,68 @@ do_test (int argc, char *argv[]) printf ("no SIGCHLD seen for SIGCONT (optional)\n"); expecting_sigchld = 0; } - else - CHECK_SIGCHLD ("continued (before waitid)", CLD_CONTINUED, SIGCONT); + check_sigchld (CLD_CONTINUED, SIGCONT, pid); info.si_signo = 0; /* A successful call sets it to SIGCHLD. */ info.si_pid = -1; info.si_status = -1; fail = waitid (P_PID, pid, &info, WCONTINUED|WNOWAIT); - switch (fail) - { - default: - printf ("waitid WCONTINUED|WNOWAIT returned bogus value %d\n", fail); - RETURN (EXIT_FAILURE); - case -1: - printf ("waitid WCONTINUED|WNOWAIT on continued: %m\n"); - RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); - case 0: - if (info.si_signo != SIGCHLD) - { - printf ("waitid WCONTINUED|WNOWAIT on continued signal %d\n", - info.si_signo); - RETURN (EXIT_FAILURE); - } - if (info.si_code != CLD_CONTINUED) - { - printf ("waitid WCONTINUED|WNOWAIT on continued code %d\n", - info.si_code); - RETURN (EXIT_FAILURE); - } - if (info.si_status != SIGCONT) - { - printf ("waitid WCONTINUED|WNOWAIT on continued status %d\n", - info.si_status); - RETURN (EXIT_FAILURE); - } - if (info.si_pid != pid) - { - printf ("waitid WCONTINUED|WNOWAIT on continued pid %d != %d\n", - info.si_pid, pid); - RETURN (EXIT_FAILURE); - } - } + if (fail == -1 && errno == ENOTSUP) + FAIL_RET ("waitid WCONTINUED|WNOWAIT on continued: %m"); + TEST_COMPARE (fail, 0); + TEST_COMPARE (info.si_signo, SIGCHLD); + TEST_COMPARE (info.si_code, CLD_CONTINUED); + TEST_COMPARE (info.si_status, SIGCONT); + TEST_COMPARE (info.si_pid, pid); /* That should leave the CLD_CONTINUED state waiting to be seen again. */ info.si_signo = 0; /* A successful call sets it to SIGCHLD. */ info.si_pid = -1; info.si_status = -1; fail = waitid (P_PID, pid, &info, WCONTINUED); - switch (fail) - { - default: - printf ("waitid WCONTINUED returned bogus value %d\n", fail); - RETURN (EXIT_FAILURE); - case -1: - printf ("waitid WCONTINUED on continued: %m\n"); - RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); - case 0: - if (info.si_signo != SIGCHLD) - { - printf ("waitid WCONTINUED on continued signal %d\n", info.si_signo); - RETURN (EXIT_FAILURE); - } - if (info.si_code != CLD_CONTINUED) - { - printf ("waitid WCONTINUED on continued code %d\n", info.si_code); - RETURN (EXIT_FAILURE); - } - if (info.si_status != SIGCONT) - { - printf ("waitid WCONTINUED on continued status %d\n", - info.si_status); - RETURN (EXIT_FAILURE); - } - if (info.si_pid != pid) - { - printf ("waitid WCONTINUED on continued pid %d != %d\n", - info.si_pid, pid); - RETURN (EXIT_FAILURE); - } - } + if (fail == -1 && errno == ENOTSUP) + FAIL_RET ("waitid WCONTINUED on continued: %m"); + TEST_COMPARE (fail, 0); + TEST_COMPARE (info.si_signo, SIGCHLD); + TEST_COMPARE (info.si_code, CLD_CONTINUED); + TEST_COMPARE (info.si_status, SIGCONT); + TEST_COMPARE (info.si_pid, pid); /* Now try a wait that should not succeed. */ info.si_signo = 0; /* A successful call sets it to SIGCHLD. */ fail = waitid (P_PID, pid, &info, WCONTINUED|WNOHANG); - switch (fail) - { - default: - printf ("waitid returned bogus value %d\n", fail); - RETURN (EXIT_FAILURE); - case -1: - printf ("waitid WCONTINUED|WNOHANG on waited continued: %m\n"); - RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); - case 0: - if (info.si_signo == 0) - break; - if (info.si_signo == SIGCHLD) - printf ("waitid WCONTINUED|WNOHANG on waited continued status %d\n", - info.si_status); - else - printf ("waitid WCONTINUED|WNOHANG on waited continued signal %d\n", - info.si_signo); - RETURN (EXIT_FAILURE); - } + if (fail == -1 && errno == ENOTSUP) + FAIL_RET ("waitid WCONTINUED|WNOHANG on waited continued: %m"); + TEST_COMPARE (fail, 0); + TEST_COMPARE (info.si_signo, 0); /* Now stop him again and test waitpid with WCONTINUED. */ expecting_sigchld = 1; if (kill (pid, SIGSTOP) != 0) - { - printf ("kill (%d, SIGSTOP): %m\n", pid); - RETURN (EXIT_FAILURE); - } + FAIL_RET ("kill (%d, SIGSTOP): %m\n", pid); - /* Give the child a chance to stop. The waitpid call below will block - until it has stopped, but if we are real quick and enter the waitpid - system call before the SIGCHLD has been generated, then it will be - discarded and never delivered. */ - sleep (3); + /* Wait the child stop. The waitid call below will block until it has + stopped, but if we are real quick and enter the waitid system call + before the SIGCHLD has been generated, then it will be discarded and + never delivered. */ + support_process_state_wait (pid, stop_state); - pid_t wpid = waitpid (pid, &fail, WUNTRACED); - if (wpid < 0) - { - printf ("waitpid WUNTRACED on stopped: %m\n"); - RETURN (EXIT_FAILURE); - } - else if (wpid != pid) - { - printf ("waitpid WUNTRACED on stopped returned %d != %d (status %x)\n", - wpid, pid, fail); - RETURN (EXIT_FAILURE); - } - else if (!WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail) - || WIFCONTINUED (fail) || WSTOPSIG (fail) != SIGSTOP) - { - printf ("waitpid WUNTRACED on stopped: status %x\n", fail); - RETURN (EXIT_FAILURE); - } - CHECK_SIGCHLD ("stopped (after waitpid)", CLD_STOPPED, SIGSTOP); + fail = waitid (type, pid, &info, WEXITED|WSTOPPED); + TEST_COMPARE (fail, 0); + TEST_COMPARE (info.si_signo, SIGCHLD); + TEST_COMPARE (info.si_code, CLD_STOPPED); + TEST_COMPARE (info.si_status, SIGSTOP); + TEST_COMPARE (info.si_pid, pid); + + check_sigchld (CLD_STOPPED, SIGSTOP, pid); expecting_sigchld = 1; + if (kill (pid, SIGCONT) != 0) - { - printf ("kill (%d, SIGCONT): %m\n", pid); - RETURN (EXIT_FAILURE); - } + FAIL_RET ("kill (%d, SIGCONT): %m\n", pid); /* Wait for the child to have continued. */ - sleep (2); + support_process_state_wait (pid, process_state_sleeping); if (expecting_sigchld) { @@ -377,142 +208,98 @@ do_test (int argc, char *argv[]) expecting_sigchld = 0; } else - CHECK_SIGCHLD ("continued (before waitpid)", CLD_CONTINUED, SIGCONT); - - wpid = waitpid (pid, &fail, WCONTINUED); - if (wpid < 0) - { - if (errno == EINVAL) - printf ("waitpid does not support WCONTINUED\n"); - else - { - printf ("waitpid WCONTINUED on continued: %m\n"); - RETURN (EXIT_FAILURE); - } - } - else if (wpid != pid) - { - printf ("\ -waitpid WCONTINUED on continued returned %d != %d (status %x)\n", - wpid, pid, fail); - RETURN (EXIT_FAILURE); - } - else if (WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail) - || !WIFCONTINUED (fail)) - { - printf ("waitpid WCONTINUED on continued: status %x\n", fail); - RETURN (EXIT_FAILURE); - } + check_sigchld (CLD_CONTINUED, SIGCONT, pid); + + fail = waitid (type, pid, &info, WCONTINUED); + TEST_COMPARE (fail, 0); + TEST_COMPARE (info.si_signo, SIGCHLD); + TEST_COMPARE (info.si_code, CLD_CONTINUED); + TEST_COMPARE (info.si_status, SIGCONT); + TEST_COMPARE (info.si_pid, pid); #endif expecting_sigchld = 1; /* Die, child, die! */ if (kill (pid, SIGKILL) != 0) - { - printf ("kill (%d, SIGKILL): %m\n", pid); - RETURN (EXIT_FAILURE); - } + FAIL_RET ("kill (%d, SIGKILL): %m\n", pid); #ifdef WNOWAIT info.si_signo = 0; /* A successful call sets it to SIGCHLD. */ info.si_pid = -1; info.si_status = -1; - fail = waitid (P_PID, pid, &info, WEXITED|WNOWAIT); - switch (fail) - { - default: - printf ("waitid WNOWAIT returned bogus value %d\n", fail); - RETURN (EXIT_FAILURE); - case -1: - printf ("waitid WNOWAIT on killed: %m\n"); - RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); - case 0: - if (info.si_signo != SIGCHLD) - { - printf ("waitid WNOWAIT on killed signal %d\n", info.si_signo); - RETURN (EXIT_FAILURE); - } - if (info.si_code != CLD_KILLED) - { - printf ("waitid WNOWAIT on killed code %d\n", info.si_code); - RETURN (EXIT_FAILURE); - } - if (info.si_status != SIGKILL) - { - printf ("waitid WNOWAIT on killed status %d\n", info.si_status); - RETURN (EXIT_FAILURE); - } - if (info.si_pid != pid) - { - printf ("waitid WNOWAIT on killed pid %d != %d\n", info.si_pid, pid); - RETURN (EXIT_FAILURE); - } - } + fail = waitid (type, pid, &info, WEXITED|WNOWAIT); + if (fail == -1 && errno == ENOTSUP) + FAIL_RET ("waitid WNOHANG on killed: %m"); + TEST_COMPARE (fail, 0); + TEST_COMPARE (info.si_signo, SIGCHLD); + TEST_COMPARE (info.si_code, CLD_KILLED); + TEST_COMPARE (info.si_status, SIGKILL); + TEST_COMPARE (info.si_pid, pid); #else - /* Allow enough time to be sure the child died; we didn't synchronize. */ - sleep (2); + support_process_state_wait (pid, process_state_zombie); #endif - - CHECK_SIGCHLD ("killed", CLD_KILLED, SIGKILL); + check_sigchld (CLD_KILLED, SIGKILL, pid); info.si_signo = 0; /* A successful call sets it to SIGCHLD. */ info.si_pid = -1; info.si_status = -1; - fail = waitid (P_PID, pid, &info, WEXITED|WNOHANG); - switch (fail) - { - default: - printf ("waitid WNOHANG returned bogus value %d\n", fail); - RETURN (EXIT_FAILURE); - case -1: - printf ("waitid WNOHANG on killed: %m\n"); - RETURN (EXIT_FAILURE); - case 0: - if (info.si_signo != SIGCHLD) - { - printf ("waitid WNOHANG on killed signal %d\n", info.si_signo); - RETURN (EXIT_FAILURE); - } - if (info.si_code != CLD_KILLED) - { - printf ("waitid WNOHANG on killed code %d\n", info.si_code); - RETURN (EXIT_FAILURE); - } - if (info.si_status != SIGKILL) - { - printf ("waitid WNOHANG on killed status %d\n", info.si_status); - RETURN (EXIT_FAILURE); - } - if (info.si_pid != pid) - { - printf ("waitid WNOHANG on killed pid %d != %d\n", info.si_pid, pid); - RETURN (EXIT_FAILURE); - } - } + fail = waitid (type, pid, &info, WEXITED | WNOHANG); + TEST_COMPARE (fail, 0); + TEST_COMPARE (info.si_signo, SIGCHLD); + TEST_COMPARE (info.si_code, CLD_KILLED); + TEST_COMPARE (info.si_status, SIGKILL); + TEST_COMPARE (info.si_pid, pid); fail = waitid (P_PID, pid, &info, WEXITED); - if (fail == -1) - { - if (errno != ECHILD) - { - printf ("waitid WEXITED on killed: %m\n"); - RETURN (EXIT_FAILURE); - } - } - else + TEST_COMPARE (fail, -1); + TEST_COMPARE (errno, ECHILD); + + return 0; +} + +static int +do_test_waitid (idtype_t type) +{ + expecting_sigchld = 1; + spurious_sigchld = 0; + +#ifdef SA_SIGINFO + { + struct sigaction sa; + sa.sa_flags = SA_SIGINFO | SA_RESTART; + sa.sa_sigaction = sigchld; + sigemptyset (&sa.sa_mask); + xsigaction (SIGCHLD, &sa, NULL); + } +#endif + + pid_t pid = xfork (); + if (pid == 0) { - printf ("waitid WEXITED returned bogus value %d\n", fail); - RETURN (EXIT_FAILURE); + test_child (type == P_PGID || type == P_ALL); + _exit (127); } -#undef RETURN - out: + int ret = do_test_waitd_common (type, pid); + if (spurious_sigchld) - status = EXIT_FAILURE; - signal (SIGCHLD, SIG_IGN); + ret = EXIT_FAILURE; + xsignal (SIGCHLD, SIG_IGN); kill (pid, SIGKILL); /* Make sure it's dead if we bailed early. */ - return status; + return ret; +} + +static int +do_test (void) +{ + int ret = 0; + + ret |= do_test_waitid (P_PID); + ret |= do_test_waitid (P_PGID); + ret |= do_test_waitid (P_ALL); + + return ret; } -#include "../test-skeleton.c" +#include