From patchwork Fri Jul 10 08:01:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 1326544 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.linux.it (client-ip=2001:1418:10:5::2; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=gDc0oFIu; dkim-atps=neutral Received: from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4B35B00Pqjz9sRN for ; Fri, 10 Jul 2020 18:02:31 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 2061B3C53D7 for ; Fri, 10 Jul 2020 10:02:29 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-4.smtp.seeweb.it (in-4.smtp.seeweb.it [217.194.8.4]) by picard.linux.it (Postfix) with ESMTP id 9C8623C53A1 for ; Fri, 10 Jul 2020 10:02:07 +0200 (CEST) Received: from mail-pg1-x542.google.com (mail-pg1-x542.google.com [IPv6:2607:f8b0:4864:20::542]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by in-4.smtp.seeweb.it (Postfix) with ESMTPS id 082841001BC3 for ; Fri, 10 Jul 2020 10:02:06 +0200 (CEST) Received: by mail-pg1-x542.google.com with SMTP id l63so2166830pge.12 for ; Fri, 10 Jul 2020 01:02:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Rua2VAeQI487EiuK/tF/hf0YT1Oev3tc2T0I3jown88=; b=gDc0oFIuIypnIoIshPDG1wZFMzhJ3IvXTDkNwlsAtWJXCFWGYN5sBFWiluGR93z+wN tAEGurwGGTEW0rIUTB5RqStW8BsobLzaZY2K4lTtca32hzgRAmEo1xq4Z+wWU4wITWC7 9zmzPC+rwouU9PoNlyzvgPGHafUI2w8NU8LOAweuzp22XHwrXf6p+njAc1p4BDXnSnUo rIXQ25QIHMkVEjspUjs2iJBNIf+yNza/LvDISLH1yZkXj+itMtz/lE/m/UF1FpoA6P1G 32CzFz3ZdjHIK43edDFn9btdKH7wicrt5pCfjvOqiPMLUOFztNTG/gAmiczmE2Om+4bH O+EA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Rua2VAeQI487EiuK/tF/hf0YT1Oev3tc2T0I3jown88=; b=JokFZqgTIoOVC/THhTYhRrFKZ5WLOsLkc5cYuJLEBCdJdKHpEE3zIaGC0yiCd/UCWt 3WqTTHbGYyr2lVkTdBXCIoDYtK2TSgWsPcYPFvLJxqDk53YQoNuydcz1OJuK9pT/5E6F ag/K2rZFG+ra2+5eh6ylgolRASp+FZ+UCu6I8vaJskAdmz4nOyr79YXzk4nQbPUIb56C hNDgaTmsgwdJywQEpt3joxFs2DoeaJOJ9hYLThxpexRBSipJvDbJIukSNxPGru5MPuXO whJ1C2iWbFnjJmXusokcEi/MP7oH0JbvbK2OWlStwltAGjZxg2lpgLNRTHDBPJVhbCpj FyYQ== X-Gm-Message-State: AOAM533kPp4IQqbPxO15qCh+YQdC3mNMCbjifyz0t5MwfZBN9ZPbEcHF 6hkgrojuZTEXylqxgPShUTZdEUibwq4= X-Google-Smtp-Source: ABdhPJx2mBkiilYATvSlrj2DErAa6AUBUoQat2/Cq/SFroArExZg27UtdraD65YQPuU6esNVmjmooA== X-Received: by 2002:a65:63d4:: with SMTP id n20mr59653370pgv.213.1594368123179; Fri, 10 Jul 2020 01:02:03 -0700 (PDT) Received: from localhost ([122.172.34.142]) by smtp.gmail.com with ESMTPSA id ev14sm4817292pjb.0.2020.07.10.01.02.01 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Jul 2020 01:02:02 -0700 (PDT) From: Viresh Kumar To: ltp@lists.linux.it Date: Fri, 10 Jul 2020 13:31:48 +0530 Message-Id: <64f602221a90899e734c7075cef4f449feb3b943.1594367611.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.25.0.rc1.19.g042ed3e048af In-Reply-To: References: MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.99.2 at in-4.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.1 required=7.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,SPF_HELO_NONE,SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-4.smtp.seeweb.it Subject: [LTP] [RFC 3/3] syscalls: sigwait: Separate out code to relevant folders X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Viresh Kumar , Vincent Guittot Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" The way it is implemented currently is very confusing, all the source code is present in one file which is referenced from 4 directories to test different syscalls. The relevant source gets build magically based on some flag passed in Makefile. Move the common part to a new library and the relevant part to their syscall folders. Signed-off-by: Viresh Kumar --- include/libsigwait.h | 45 ++ libs/libltpsigwait/Makefile | 11 + libs/libltpsigwait/sigwait.c | 428 +++++++++++++ .../kernel/syscalls/rt_sigtimedwait/Makefile | 10 +- .../rt_sigtimedwait/rt_sigtimedwait01.c | 78 +++ .../kernel/syscalls/sigtimedwait/Makefile | 9 +- .../syscalls/sigtimedwait/sigtimedwait01.c | 37 ++ testcases/kernel/syscalls/sigwait/Makefile | 9 +- testcases/kernel/syscalls/sigwait/sigwait01.c | 37 ++ .../kernel/syscalls/sigwaitinfo/Makefile | 4 +- .../syscalls/sigwaitinfo/sigwaitinfo01.c | 575 +----------------- 11 files changed, 661 insertions(+), 582 deletions(-) create mode 100644 include/libsigwait.h create mode 100644 libs/libltpsigwait/Makefile create mode 100644 libs/libltpsigwait/sigwait.c create mode 100644 testcases/kernel/syscalls/rt_sigtimedwait/rt_sigtimedwait01.c create mode 100644 testcases/kernel/syscalls/sigtimedwait/sigtimedwait01.c create mode 100644 testcases/kernel/syscalls/sigwait/sigwait01.c diff --git a/include/libsigwait.h b/include/libsigwait.h new file mode 100644 index 000000000000..7202fc78fde8 --- /dev/null +++ b/include/libsigwait.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Linaro Limited. All rights reserved. + * Author: Viresh Kumar + */ + +#ifndef SIGWAIT_H__ +#define SIGWAIT_H__ + +#include "tst_test.h" +#include "tst_timer.h" +#include + +/* swi: sigwaitinfo() */ +typedef int (*swi_func) (const sigset_t * set, siginfo_t * info, + void * timeout); +typedef void (*test_func) (swi_func, int, enum tst_ts_type type); + +struct sigwait_test_desc { + test_func tf; + int signo; +}; + +void test_empty_set(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED); +void test_timeout(swi_func sigwaitinfo, int signo, enum tst_ts_type type); +void test_unmasked_matching(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED); +void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED); +void test_masked_matching(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED); +void test_masked_matching_rt(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED); +void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED); +void test_bad_address(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED); +void test_bad_address2(swi_func sigwaitinfo, int signo LTP_ATTRIBUTE_UNUSED, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED); +void test_bad_address3(swi_func sigwaitinfo, int signo LTP_ATTRIBUTE_UNUSED, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED); +void sigwait_setup(void); +void sigwait_cleanup(void); +#endif /* SIGWAIT_H__ */ diff --git a/libs/libltpsigwait/Makefile b/libs/libltpsigwait/Makefile new file mode 100644 index 000000000000..e0ea025ade2b --- /dev/null +++ b/libs/libltpsigwait/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2020 Viresh Kumar + +top_srcdir ?= ../.. + +include $(top_srcdir)/include/mk/env_pre.mk + +INTERNAL_LIB := libltpsigwait.a + +include $(top_srcdir)/include/mk/lib.mk +include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/libs/libltpsigwait/sigwait.c b/libs/libltpsigwait/sigwait.c new file mode 100644 index 000000000000..5fbcdebf1295 --- /dev/null +++ b/libs/libltpsigwait/sigwait.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Copyright (c) Jiri Palecek, 2009 */ + +#define TST_NO_DEFAULT_MAIN +#include +#include +#include +#include "lapi/syscalls.h" +#include "libsigwait.h" +#include "tst_sig_proc.h" + +/* Report success iff TST_RET and TST_ERR are equal to + exp_return and exp_errno, resp., and cond is true. If cond is not + true, report condition_errmsg +*/ +static void report_success_cond(const char *func, int line, + long exp_return, int exp_errno, int condition, + char *condition_errmsg) +{ + if (exp_return == TST_RET + && (exp_return != -1 || exp_errno == TST_ERR)) + if (condition) + tst_res(TPASS, "%s (%d): Test passed", func, line); + else + tst_res(TFAIL, "%s (%d): %s", func, line, + condition_errmsg); + else if (TST_RET != -1) + tst_res(TFAIL, + "%s (%d): Unexpected return value; expected %ld, got %ld", + func, line, exp_return, TST_RET); + else + tst_res(TFAIL | TTERRNO, "%s (%d): Unexpected failure", + func, line); +} + +#define REPORT_SUCCESS_COND(exp_return, exp_errno, condition, condition_errmsg) \ + report_success_cond(__FUNCTION__, __LINE__, exp_return, exp_errno, condition, condition_errmsg); + +/* Report success iff TST_RET and TST_ERR are equal to + exp_return and exp_errno, resp. +*/ +#define REPORT_SUCCESS(exp_return, exp_errno) \ + REPORT_SUCCESS_COND(exp_return, exp_errno, 1, ""); + +void test_empty_set(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) +{ + sigset_t sigs; + siginfo_t si; + pid_t child; + + TEST(sigemptyset(&sigs)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); + + /* Run a child that will wake us up */ + child = create_sig_proc(signo, INT_MAX, 100000); + + TEST(sigwaitinfo(&sigs, &si, NULL)); + REPORT_SUCCESS(-1, EINTR); + + SAFE_KILL(child, SIGTERM); + SAFE_WAIT(NULL); +} + +void test_timeout(swi_func sigwaitinfo, int signo, enum tst_ts_type type) +{ + sigset_t sigs; + siginfo_t si; + pid_t child; + struct tst_ts ts; + + ts.type = type; + tst_ts_set_sec(&ts, 1); + tst_ts_set_nsec(&ts, 0); + + TEST(sigemptyset(&sigs)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); + + /* Run a child that will wake us up */ + child = create_sig_proc(signo, INT_MAX, 100000); + + TEST(sigwaitinfo(&sigs, &si, tst_ts_get(&ts))); + REPORT_SUCCESS(-1, EAGAIN); + + SAFE_KILL(child, SIGTERM); + SAFE_WAIT(NULL); +} + +/* Note: sigwait-ing for a signal that is not blocked is unspecified + * by POSIX; but works for non-ignored signals under Linux + */ +void test_unmasked_matching(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) +{ + sigset_t sigs; + siginfo_t si; + pid_t child; + + TEST(sigemptyset(&sigs)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); + + TEST(sigaddset(&sigs, signo)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigaddset() failed"); + + /* Run a child that will wake us up */ + child = create_sig_proc(signo, INT_MAX, 100000); + + TEST(sigwaitinfo(&sigs, &si, NULL)); + REPORT_SUCCESS_COND(signo, 0, si.si_pid == child + && si.si_code == SI_USER + && si.si_signo == signo, "Struct siginfo mismatch"); + + SAFE_KILL(child, SIGTERM); + SAFE_WAIT(NULL); +} + +void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) +{ + sigset_t sigs; + pid_t child; + + TEST(sigemptyset(&sigs)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); + + TEST(sigaddset(&sigs, signo)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigaddset() failed"); + + /* Run a child that will wake us up */ + child = create_sig_proc(signo, INT_MAX, 100000); + + TEST(sigwaitinfo(&sigs, NULL, NULL)); + REPORT_SUCCESS(signo, 0); + + SAFE_KILL(child, SIGTERM); + SAFE_WAIT(NULL); +} + +void test_masked_matching(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) +{ + sigset_t sigs, oldmask; + siginfo_t si; + pid_t child; + + TEST(sigemptyset(&sigs)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); + + TEST(sigaddset(&sigs, signo)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigaddset() failed"); + + /* let's not get interrupted by our dying child */ + TEST(sigaddset(&sigs, SIGCHLD)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigaddset() failed"); + + TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigprocmask() failed"); + + /* don't wait on a SIGCHLD */ + TEST(sigdelset(&sigs, SIGCHLD)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigdelset() failed"); + + /* Run a child that will wake us up */ + child = create_sig_proc(signo, 1, 0); + + TEST(sigwaitinfo(&sigs, &si, NULL)); + REPORT_SUCCESS_COND(signo, 0, si.si_pid == child + && si.si_code == SI_USER + && si.si_signo == signo, "Struct siginfo mismatch"); + + TEST(sigprocmask(SIG_SETMASK, &oldmask, &oldmask)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "restoring original signal mask failed"); + + if (sigismember(&oldmask, signo)) + tst_res(TPASS, "sigwaitinfo restored the original mask"); + else + tst_res(TFAIL, + "sigwaitinfo failed to restore the original mask"); + + SAFE_KILL(child, SIGTERM); + SAFE_WAIT(NULL); +} + +void test_masked_matching_rt(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) +{ + sigset_t sigs, oldmask; + siginfo_t si; + pid_t child[2]; + int status; + + signo = SIGRTMIN + 1; + + TEST(sigemptyset(&sigs)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); + + TEST(sigaddset(&sigs, signo)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigaddset() failed"); + + TEST(sigaddset(&sigs, signo + 1)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigaddset() failed"); + + /* let's not get interrupted by our dying child */ + TEST(sigaddset(&sigs, SIGCHLD)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigaddset() failed"); + + TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigprocmask() failed"); + + /* don't wait on a SIGCHLD */ + TEST(sigdelset(&sigs, SIGCHLD)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigdelset() failed"); + + /* Run a child that will wake us up */ + child[0] = create_sig_proc(signo, 1, 0); + child[1] = create_sig_proc(signo + 1, 1, 0); + + /* Ensure that the signals have been sent */ + SAFE_WAITPID(child[0], &status, 0); + SAFE_WAITPID(child[1], &status, 0); + + TEST(sigwaitinfo(&sigs, &si, NULL)); + REPORT_SUCCESS_COND(signo, 0, si.si_pid == child[0] + && si.si_code == SI_USER + && si.si_signo == signo, "Struct siginfo mismatch"); + + /* eat the other signal */ + TEST(sigwaitinfo(&sigs, &si, NULL)); + REPORT_SUCCESS_COND(signo + 1, 0, si.si_pid == child[1] + && si.si_code == SI_USER + && si.si_signo == signo + 1, + "Struct siginfo mismatch"); + + TEST(sigprocmask(SIG_SETMASK, &oldmask, &oldmask)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "restoring original signal mask failed"); + + if (sigismember(&oldmask, signo)) + tst_res(TPASS, "sigwaitinfo restored the original mask"); + else + tst_res(TFAIL, + "sigwaitinfo failed to restore the original mask"); +} + +void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) +{ + sigset_t sigs, oldmask; + pid_t child; + + TEST(sigemptyset(&sigs)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); + + TEST(sigaddset(&sigs, signo)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigaddset() failed"); + + /* let's not get interrupted by our dying child */ + TEST(sigaddset(&sigs, SIGCHLD)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigaddset() failed"); + + TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigprocmask() failed"); + + /* don't wait on a SIGCHLD */ + TEST(sigdelset(&sigs, SIGCHLD)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigdelset() failed"); + + /* Run a child that will wake us up */ + child = create_sig_proc(signo, 1, 0); + + TEST(sigwaitinfo(&sigs, NULL, NULL)); + REPORT_SUCCESS(signo, 0); + + TEST(sigprocmask(SIG_SETMASK, &oldmask, &oldmask)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "restoring original signal mask failed"); + + if (sigismember(&oldmask, signo)) + tst_res(TPASS, "sigwaitinfo restored the original mask"); + else + tst_res(TFAIL, + "sigwaitinfo failed to restore the original mask"); + + SAFE_KILL(child, SIGTERM); + SAFE_WAIT(NULL); +} + +void test_bad_address(swi_func sigwaitinfo, int signo, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) +{ + sigset_t sigs, oldmask; + pid_t child; + + TEST(sigemptyset(&sigs)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); + + TEST(sigaddset(&sigs, signo)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigaddset() failed"); + + /* let's not get interrupted by our dying child */ + TEST(sigaddset(&sigs, SIGCHLD)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigaddset() failed"); + + TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigprocmask() failed"); + + /* don't wait on a SIGCHLD */ + TEST(sigdelset(&sigs, SIGCHLD)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigdelset() failed"); + + /* Run a child that will wake us up */ + child = create_sig_proc(signo, 1, 0); + + TEST(sigwaitinfo(&sigs, (void *)1, NULL)); + REPORT_SUCCESS(-1, EFAULT); + + TEST(sigprocmask(SIG_SETMASK, &oldmask, &oldmask)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigprocmask() failed"); + + SAFE_KILL(child, SIGTERM); + SAFE_WAIT(NULL); +} + +void test_bad_address2(swi_func sigwaitinfo, int signo LTP_ATTRIBUTE_UNUSED, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) +{ + pid_t pid; + int status; + + switch (pid = fork()) { + case -1: + tst_brk(TBROK | TERRNO, "fork() failed"); + case 0: + signal(SIGSEGV, SIG_DFL); + + /* + * depending on glibc implementation we should + * either crash or get EFAULT + */ + TEST(sigwaitinfo((void *)1, NULL, NULL)); + + if (TST_RET == -1 && TST_ERR == EFAULT) + _exit(0); + + tst_res(TINFO | TTERRNO, "swi_func returned: %ld", + TST_RET); + _exit(1); + break; + default: + break; + } + + SAFE_WAITPID(pid, &status, 0); + + if ((WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) + || (WIFEXITED(status) && WEXITSTATUS(status) == 0)) { + tst_res(TPASS, "Test passed"); + return; + } + + if (WIFEXITED(status)) { + tst_res(TFAIL, "Unrecognised child exit code: %d", + WEXITSTATUS(status)); + } + if (WIFSIGNALED(status)) { + tst_res(TFAIL, "Unrecognised child termsig: %d", + WTERMSIG(status)); + } +} + +void test_bad_address3(swi_func sigwaitinfo, int signo LTP_ATTRIBUTE_UNUSED, + enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) +{ + sigset_t sigs; + TEST(sigemptyset(&sigs)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); + + TEST(sigwaitinfo(&sigs, NULL, (void *)1)); + REPORT_SUCCESS(-1, EFAULT); +} + +static void empty_handler(int sig LTP_ATTRIBUTE_UNUSED) +{ +} + +void sigwait_setup(void) +{ + signal(SIGUSR1, empty_handler); + signal(SIGALRM, empty_handler); + signal(SIGUSR2, SIG_IGN); + + alarm(10); /* arrange a 10 second timeout */ +} + +void sigwait_cleanup(void) +{ + alarm(0); +} diff --git a/testcases/kernel/syscalls/rt_sigtimedwait/Makefile b/testcases/kernel/syscalls/rt_sigtimedwait/Makefile index 9524bf91e65e..77265aca22d7 100644 --- a/testcases/kernel/syscalls/rt_sigtimedwait/Makefile +++ b/testcases/kernel/syscalls/rt_sigtimedwait/Makefile @@ -3,14 +3,10 @@ top_srcdir ?= ../../../.. -include $(top_srcdir)/include/mk/testcases.mk - -CPPFLAGS += -DTEST_RT_SIGTIMEDWAIT +LTPLIBS = ltpsigwait -rt_sigtimedwait01: $(abs_srcdir)/../sigwaitinfo/sigwaitinfo01.c - $(LINK.c) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION) +include $(top_srcdir)/include/mk/testcases.mk -MAKE_TARGETS := rt_sigtimedwait01 +LDLIBS += -lltpsigwait include $(top_srcdir)/include/mk/generic_leaf_target.mk - diff --git a/testcases/kernel/syscalls/rt_sigtimedwait/rt_sigtimedwait01.c b/testcases/kernel/syscalls/rt_sigtimedwait/rt_sigtimedwait01.c new file mode 100644 index 000000000000..8b6153744938 --- /dev/null +++ b/testcases/kernel/syscalls/rt_sigtimedwait/rt_sigtimedwait01.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Copyright (c) Jiri Palecek, 2009 */ + +#include "libsigwait.h" + +static int my_rt_sigtimedwait(const sigset_t * set, siginfo_t * info, + void *timeout) +{ + /* _NSIG is always the right number of bits of signal map for all arches */ + return tst_syscall(__NR_rt_sigtimedwait, set, info, timeout, _NSIG/8); +} + +#if (__NR_rt_sigtimedwait_time64 != __LTP__NR_INVALID_SYSCALL) +static int my_rt_sigtimedwait_time64(const sigset_t * set, siginfo_t * info, + void *timeout) +{ + /* _NSIG is always the right number of bits of signal map for all arches */ + return tst_syscall(__NR_rt_sigtimedwait_time64, set, info, timeout, _NSIG/8); +} +#endif + +struct sigwait_test_desc tests[] = { + { test_empty_set, SIGUSR1}, + { test_unmasked_matching, SIGUSR1}, + { test_masked_matching, SIGUSR1}, + { test_unmasked_matching_noinfo, SIGUSR1}, + { test_masked_matching_noinfo, SIGUSR1}, + { test_bad_address, SIGUSR1}, + { test_bad_address2, SIGUSR1}, + { test_bad_address3, SIGUSR1}, + { test_timeout, 0}, + /* Special cases */ + /* 1: sigwaitinfo does respond to ignored signal */ + { test_masked_matching, SIGUSR2}, + /* 2: An ignored signal doesn't cause sigwaitinfo to return EINTR */ + { test_timeout, SIGUSR2}, + /* 3: The handler is not called when the signal is waited for by sigwaitinfo */ + { test_masked_matching, SIGTERM}, + /* 4: Simultaneous realtime signals are delivered in the order of increasing signal number */ + { test_masked_matching_rt, -1}, +}; + +static struct test_variants { + swi_func swi; + enum tst_ts_type type; + char *desc; +} variants[] = { +#if (__NR_rt_sigtimedwait != __LTP__NR_INVALID_SYSCALL) + { .swi = my_rt_sigtimedwait, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"}, +#endif + +#if (__NR_rt_sigtimedwait_time64 != __LTP__NR_INVALID_SYSCALL) + { .swi = my_rt_sigtimedwait_time64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"}, +#endif +}; + +static void run(unsigned int i) +{ + struct test_variants *tv = &variants[tst_variant]; + struct sigwait_test_desc *tc = &tests[i]; + + tc->tf(tv->swi, tc->signo, tv->type); +} + +static void setup(void) +{ + tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc); + sigwait_setup(); +} + +static struct tst_test test = { + .test= run, + .tcnt = ARRAY_SIZE(tests), + .test_variants = ARRAY_SIZE(variants), + .setup = setup, + .cleanup = sigwait_cleanup, + .forks_child = 1, +}; diff --git a/testcases/kernel/syscalls/sigtimedwait/Makefile b/testcases/kernel/syscalls/sigtimedwait/Makefile index 7ba1f9c0571d..77265aca22d7 100644 --- a/testcases/kernel/syscalls/sigtimedwait/Makefile +++ b/testcases/kernel/syscalls/sigtimedwait/Makefile @@ -3,13 +3,10 @@ top_srcdir ?= ../../../.. -include $(top_srcdir)/include/mk/testcases.mk - -CPPFLAGS += -DTEST_SIGTIMEDWAIT +LTPLIBS = ltpsigwait -sigtimedwait01: $(abs_srcdir)/../sigwaitinfo/sigwaitinfo01.c - $(LINK.c) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION) +include $(top_srcdir)/include/mk/testcases.mk -MAKE_TARGETS := sigtimedwait01 +LDLIBS += -lltpsigwait include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/sigtimedwait/sigtimedwait01.c b/testcases/kernel/syscalls/sigtimedwait/sigtimedwait01.c new file mode 100644 index 000000000000..946d8e7239a0 --- /dev/null +++ b/testcases/kernel/syscalls/sigtimedwait/sigtimedwait01.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Copyright (c) Jiri Palecek, 2009 */ + +#include "libsigwait.h" + +static int my_sigtimedwait(const sigset_t * set, siginfo_t * info, + void *timeout) +{ + return sigtimedwait(set, info, timeout); +} + +struct sigwait_test_desc tests[] = { + { test_empty_set, SIGUSR1}, + { test_unmasked_matching, SIGUSR1}, + { test_masked_matching, SIGUSR1}, + { test_unmasked_matching_noinfo, SIGUSR1}, + { test_masked_matching_noinfo, SIGUSR1}, + { test_bad_address, SIGUSR1}, + { test_bad_address2, SIGUSR1}, + { test_bad_address3, SIGUSR1}, + { test_timeout, 0}, +}; + +static void run(unsigned int i) +{ + struct sigwait_test_desc *tc = &tests[i]; + + tc->tf(my_sigtimedwait, tc->signo, TST_LIBC_TIMESPEC); +} + +static struct tst_test test = { + .test= run, + .tcnt = ARRAY_SIZE(tests), + .setup = sigwait_setup, + .cleanup = sigwait_cleanup, + .forks_child = 1, +}; diff --git a/testcases/kernel/syscalls/sigwait/Makefile b/testcases/kernel/syscalls/sigwait/Makefile index e1e4ad486af9..77265aca22d7 100644 --- a/testcases/kernel/syscalls/sigwait/Makefile +++ b/testcases/kernel/syscalls/sigwait/Makefile @@ -3,13 +3,10 @@ top_srcdir ?= ../../../.. -include $(top_srcdir)/include/mk/testcases.mk - -CPPFLAGS += -DTEST_SIGWAIT +LTPLIBS = ltpsigwait -sigwait01: $(abs_srcdir)/../sigwaitinfo/sigwaitinfo01.c - $(LINK.c) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION) +include $(top_srcdir)/include/mk/testcases.mk -MAKE_TARGETS := sigwait01 +LDLIBS += -lltpsigwait include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/sigwait/sigwait01.c b/testcases/kernel/syscalls/sigwait/sigwait01.c new file mode 100644 index 000000000000..563d15635fd9 --- /dev/null +++ b/testcases/kernel/syscalls/sigwait/sigwait01.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Copyright (c) Jiri Palecek, 2009 */ + +#include "libsigwait.h" + +static int my_sigwait(const sigset_t * set, + siginfo_t * info LTP_ATTRIBUTE_UNUSED, + void *timeout LTP_ATTRIBUTE_UNUSED) +{ + int ret; + int err = sigwait(set, &ret); + + if (err == 0) + return ret; + errno = err; + return -1; +} + +struct sigwait_test_desc tests[] = { + { test_unmasked_matching_noinfo, SIGUSR1}, + { test_masked_matching_noinfo, SIGUSR1}, +}; + +static void run(unsigned int i) +{ + struct sigwait_test_desc *tc = &tests[i]; + + tc->tf(my_sigwait, tc->signo, TST_LIBC_TIMESPEC); +} + +static struct tst_test test = { + .test= run, + .tcnt = ARRAY_SIZE(tests), + .setup = sigwait_setup, + .cleanup = sigwait_cleanup, + .forks_child = 1, +}; diff --git a/testcases/kernel/syscalls/sigwaitinfo/Makefile b/testcases/kernel/syscalls/sigwaitinfo/Makefile index 27c6b72c40a3..77265aca22d7 100644 --- a/testcases/kernel/syscalls/sigwaitinfo/Makefile +++ b/testcases/kernel/syscalls/sigwaitinfo/Makefile @@ -3,8 +3,10 @@ top_srcdir ?= ../../../.. +LTPLIBS = ltpsigwait + include $(top_srcdir)/include/mk/testcases.mk -CPPFLAGS += -DTEST_SIGWAITINFO +LDLIBS += -lltpsigwait include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c b/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c index 5e1baf9df774..6563d14f0ec7 100644 --- a/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c +++ b/testcases/kernel/syscalls/sigwaitinfo/sigwaitinfo01.c @@ -1,584 +1,35 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* Copyright (c) Jiri Palecek, 2009 */ -#include "tst_test.h" -#include "tst_timer.h" -#include -#include -#include -#include -#include "lapi/syscalls.h" -#include "tst_sig_proc.h" +#include "libsigwait.h" -/* Report success iff TST_RET and TST_ERR are equal to - exp_return and exp_errno, resp., and cond is true. If cond is not - true, report condition_errmsg -*/ -static void report_success_cond(const char *func, int line, - long exp_return, int exp_errno, int condition, - char *condition_errmsg) -{ - if (exp_return == TST_RET - && (exp_return != -1 || exp_errno == TST_ERR)) - if (condition) - tst_res(TPASS, "%s (%d): Test passed", func, line); - else - tst_res(TFAIL, "%s (%d): %s", func, line, - condition_errmsg); - else if (TST_RET != -1) - tst_res(TFAIL, - "%s (%d): Unexpected return value; expected %ld, got %ld", - func, line, exp_return, TST_RET); - else - tst_res(TFAIL | TTERRNO, "%s (%d): Unexpected failure", - func, line); -} - -#define REPORT_SUCCESS_COND(exp_return, exp_errno, condition, condition_errmsg) \ - report_success_cond(__FUNCTION__, __LINE__, exp_return, exp_errno, condition, condition_errmsg); - -/* Report success iff TST_RET and TST_ERR are equal to - exp_return and exp_errno, resp. -*/ -#define REPORT_SUCCESS(exp_return, exp_errno) \ - REPORT_SUCCESS_COND(exp_return, exp_errno, 1, ""); - -static void empty_handler(int sig LTP_ATTRIBUTE_UNUSED) -{ -} - -typedef int (*swi_func) (const sigset_t * set, siginfo_t * info, - void * timeout); -typedef void (*test_func) (swi_func, int, enum tst_ts_type type); - -#ifdef TEST_SIGWAIT -static int my_sigwait(const sigset_t * set, siginfo_t * info, - void *timeout) -{ - int ret; - int err = sigwait(set, &ret); - - if (err == 0) - return ret; - errno = err; - return -1; -} -#endif - -#ifdef TEST_SIGWAITINFO static int my_sigwaitinfo(const sigset_t * set, siginfo_t * info, void *timeout LTP_ATTRIBUTE_UNUSED) { return sigwaitinfo(set, info); } -#endif - -#ifdef TEST_SIGTIMEDWAIT -static int my_sigtimedwait(const sigset_t * set, siginfo_t * info, - void *timeout) -{ - return sigtimedwait(set, info, timeout); -} -#endif - -#ifdef TEST_RT_SIGTIMEDWAIT -static int my_rt_sigtimedwait(const sigset_t * set, siginfo_t * info, - void *timeout) -{ - /* _NSIG is always the right number of bits of signal map for all arches */ - return tst_syscall(__NR_rt_sigtimedwait, set, info, timeout, _NSIG/8); -} - -#if (__NR_rt_sigtimedwait_time64 != __LTP__NR_INVALID_SYSCALL) -static int my_rt_sigtimedwait_time64(const sigset_t * set, siginfo_t * info, - void *timeout) -{ - /* _NSIG is always the right number of bits of signal map for all arches */ - return tst_syscall(__NR_rt_sigtimedwait_time64, set, info, timeout, _NSIG/8); -} -#endif -#endif - -void test_empty_set(swi_func sigwaitinfo, int signo, - enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) -{ - sigset_t sigs; - siginfo_t si; - pid_t child; - - TEST(sigemptyset(&sigs)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); - - /* Run a child that will wake us up */ - child = create_sig_proc(signo, INT_MAX, 100000); - - TEST(sigwaitinfo(&sigs, &si, NULL)); - REPORT_SUCCESS(-1, EINTR); - - SAFE_KILL(child, SIGTERM); - SAFE_WAIT(NULL); -} - -void test_timeout(swi_func sigwaitinfo, int signo, enum tst_ts_type type) -{ - sigset_t sigs; - siginfo_t si; - pid_t child; - struct tst_ts ts; - - ts.type = type; - tst_ts_set_sec(&ts, 1); - tst_ts_set_nsec(&ts, 0); - - TEST(sigemptyset(&sigs)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); - - /* Run a child that will wake us up */ - child = create_sig_proc(signo, INT_MAX, 100000); - - TEST(sigwaitinfo(&sigs, &si, tst_ts_get(&ts))); - REPORT_SUCCESS(-1, EAGAIN); - - SAFE_KILL(child, SIGTERM); - SAFE_WAIT(NULL); -} - -/* Note: sigwait-ing for a signal that is not blocked is unspecified - * by POSIX; but works for non-ignored signals under Linux - */ -void test_unmasked_matching(swi_func sigwaitinfo, int signo, - enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) -{ - sigset_t sigs; - siginfo_t si; - pid_t child; - - TEST(sigemptyset(&sigs)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); - - TEST(sigaddset(&sigs, signo)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigaddset() failed"); - - /* Run a child that will wake us up */ - child = create_sig_proc(signo, INT_MAX, 100000); - - TEST(sigwaitinfo(&sigs, &si, NULL)); - REPORT_SUCCESS_COND(signo, 0, si.si_pid == child - && si.si_code == SI_USER - && si.si_signo == signo, "Struct siginfo mismatch"); - - SAFE_KILL(child, SIGTERM); - SAFE_WAIT(NULL); -} - -void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo, - enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) -{ - sigset_t sigs; - pid_t child; - - TEST(sigemptyset(&sigs)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); - - TEST(sigaddset(&sigs, signo)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigaddset() failed"); - - /* Run a child that will wake us up */ - child = create_sig_proc(signo, INT_MAX, 100000); - - TEST(sigwaitinfo(&sigs, NULL, NULL)); - REPORT_SUCCESS(signo, 0); - - SAFE_KILL(child, SIGTERM); - SAFE_WAIT(NULL); -} - -void test_masked_matching(swi_func sigwaitinfo, int signo, - enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) -{ - sigset_t sigs, oldmask; - siginfo_t si; - pid_t child; - - TEST(sigemptyset(&sigs)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); - - TEST(sigaddset(&sigs, signo)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigaddset() failed"); - - /* let's not get interrupted by our dying child */ - TEST(sigaddset(&sigs, SIGCHLD)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigaddset() failed"); - - TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigprocmask() failed"); - - /* don't wait on a SIGCHLD */ - TEST(sigdelset(&sigs, SIGCHLD)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigdelset() failed"); - - /* Run a child that will wake us up */ - child = create_sig_proc(signo, 1, 0); - - TEST(sigwaitinfo(&sigs, &si, NULL)); - REPORT_SUCCESS_COND(signo, 0, si.si_pid == child - && si.si_code == SI_USER - && si.si_signo == signo, "Struct siginfo mismatch"); - - TEST(sigprocmask(SIG_SETMASK, &oldmask, &oldmask)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "restoring original signal mask failed"); - - if (sigismember(&oldmask, signo)) - tst_res(TPASS, "sigwaitinfo restored the original mask"); - else - tst_res(TFAIL, - "sigwaitinfo failed to restore the original mask"); - - SAFE_KILL(child, SIGTERM); - SAFE_WAIT(NULL); -} - -void test_masked_matching_rt(swi_func sigwaitinfo, int signo, - enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) -{ - sigset_t sigs, oldmask; - siginfo_t si; - pid_t child[2]; - int status; - - signo = SIGRTMIN + 1; - TEST(sigemptyset(&sigs)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); - - TEST(sigaddset(&sigs, signo)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigaddset() failed"); - - TEST(sigaddset(&sigs, signo + 1)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigaddset() failed"); - - /* let's not get interrupted by our dying child */ - TEST(sigaddset(&sigs, SIGCHLD)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigaddset() failed"); - - TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigprocmask() failed"); - - /* don't wait on a SIGCHLD */ - TEST(sigdelset(&sigs, SIGCHLD)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigdelset() failed"); - - /* Run a child that will wake us up */ - child[0] = create_sig_proc(signo, 1, 0); - child[1] = create_sig_proc(signo + 1, 1, 0); - - /* Ensure that the signals have been sent */ - SAFE_WAITPID(child[0], &status, 0); - SAFE_WAITPID(child[1], &status, 0); - - TEST(sigwaitinfo(&sigs, &si, NULL)); - REPORT_SUCCESS_COND(signo, 0, si.si_pid == child[0] - && si.si_code == SI_USER - && si.si_signo == signo, "Struct siginfo mismatch"); - - /* eat the other signal */ - TEST(sigwaitinfo(&sigs, &si, NULL)); - REPORT_SUCCESS_COND(signo + 1, 0, si.si_pid == child[1] - && si.si_code == SI_USER - && si.si_signo == signo + 1, - "Struct siginfo mismatch"); - - TEST(sigprocmask(SIG_SETMASK, &oldmask, &oldmask)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "restoring original signal mask failed"); - - if (sigismember(&oldmask, signo)) - tst_res(TPASS, "sigwaitinfo restored the original mask"); - else - tst_res(TFAIL, - "sigwaitinfo failed to restore the original mask"); -} - -void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo, - enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) -{ - sigset_t sigs, oldmask; - pid_t child; - - TEST(sigemptyset(&sigs)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); - - TEST(sigaddset(&sigs, signo)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigaddset() failed"); - - /* let's not get interrupted by our dying child */ - TEST(sigaddset(&sigs, SIGCHLD)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigaddset() failed"); - - TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigprocmask() failed"); - - /* don't wait on a SIGCHLD */ - TEST(sigdelset(&sigs, SIGCHLD)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigdelset() failed"); - - /* Run a child that will wake us up */ - child = create_sig_proc(signo, 1, 0); - - TEST(sigwaitinfo(&sigs, NULL, NULL)); - REPORT_SUCCESS(signo, 0); - - TEST(sigprocmask(SIG_SETMASK, &oldmask, &oldmask)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "restoring original signal mask failed"); - - if (sigismember(&oldmask, signo)) - tst_res(TPASS, "sigwaitinfo restored the original mask"); - else - tst_res(TFAIL, - "sigwaitinfo failed to restore the original mask"); - - SAFE_KILL(child, SIGTERM); - SAFE_WAIT(NULL); -} - -void test_bad_address(swi_func sigwaitinfo, int signo, - enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) -{ - sigset_t sigs, oldmask; - pid_t child; - - TEST(sigemptyset(&sigs)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); - - TEST(sigaddset(&sigs, signo)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigaddset() failed"); - - /* let's not get interrupted by our dying child */ - TEST(sigaddset(&sigs, SIGCHLD)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigaddset() failed"); - - TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigprocmask() failed"); - - /* don't wait on a SIGCHLD */ - TEST(sigdelset(&sigs, SIGCHLD)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigdelset() failed"); - - /* Run a child that will wake us up */ - child = create_sig_proc(signo, 1, 0); - - TEST(sigwaitinfo(&sigs, (void *)1, NULL)); - REPORT_SUCCESS(-1, EFAULT); - - TEST(sigprocmask(SIG_SETMASK, &oldmask, &oldmask)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigprocmask() failed"); - - SAFE_KILL(child, SIGTERM); - SAFE_WAIT(NULL); -} - -void test_bad_address2(swi_func sigwaitinfo, int signo LTP_ATTRIBUTE_UNUSED, - enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) -{ - pid_t pid; - int status; - - switch (pid = fork()) { - case -1: - tst_brk(TBROK | TERRNO, "fork() failed"); - case 0: - signal(SIGSEGV, SIG_DFL); - - /* - * depending on glibc implementation we should - * either crash or get EFAULT - */ - TEST(sigwaitinfo((void *)1, NULL, NULL)); - - if (TST_RET == -1 && TST_ERR == EFAULT) - _exit(0); - - tst_res(TINFO | TTERRNO, "swi_func returned: %ld", - TST_RET); - _exit(1); - break; - default: - break; - } - - SAFE_WAITPID(pid, &status, 0); - - if ((WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) - || (WIFEXITED(status) && WEXITSTATUS(status) == 0)) { - tst_res(TPASS, "Test passed"); - return; - } - - if (WIFEXITED(status)) { - tst_res(TFAIL, "Unrecognised child exit code: %d", - WEXITSTATUS(status)); - } - if (WIFSIGNALED(status)) { - tst_res(TFAIL, "Unrecognised child termsig: %d", - WTERMSIG(status)); - } -} - -void test_bad_address3(swi_func sigwaitinfo, int signo LTP_ATTRIBUTE_UNUSED, - enum tst_ts_type type LTP_ATTRIBUTE_UNUSED) -{ - sigset_t sigs; - TEST(sigemptyset(&sigs)); - if (TST_RET == -1) - tst_brk(TBROK | TTERRNO, "sigemptyset() failed"); - - TEST(sigwaitinfo(&sigs, NULL, (void *)1)); - REPORT_SUCCESS(-1, EFAULT); -} - -struct test_desc { - test_func tf; - swi_func swi; - int signo; -} tests[] = { -#ifdef TEST_RT_SIGTIMEDWAIT - { - test_empty_set, NULL, SIGUSR1}, { - test_unmasked_matching, NULL, SIGUSR1}, { - test_masked_matching, NULL, SIGUSR1}, { - test_unmasked_matching_noinfo, NULL, SIGUSR1}, { - test_masked_matching_noinfo, NULL, SIGUSR1}, { - test_bad_address, NULL, SIGUSR1}, { - test_bad_address2, NULL, SIGUSR1}, { - test_bad_address3, NULL, SIGUSR1}, { - test_timeout, NULL, 0}, - /* Special cases */ - /* 1: sigwaitinfo does respond to ignored signal */ - { - test_masked_matching, NULL, SIGUSR2}, - /* 2: An ignored signal doesn't cause sigwaitinfo to return EINTR */ - { - test_timeout, NULL, SIGUSR2}, - /* 3: The handler is not called when the signal is waited for by sigwaitinfo */ - { - test_masked_matching, NULL, SIGTERM}, - /* 4: Simultaneous realtime signals are delivered in the order of increasing signal number */ - { - test_masked_matching_rt, NULL, -1}, -#endif -#if defined TEST_SIGWAIT - { - test_unmasked_matching_noinfo, my_sigwait, SIGUSR1}, { - test_masked_matching_noinfo, my_sigwait, SIGUSR1}, -#endif -#if defined TEST_SIGWAITINFO - { - test_empty_set, my_sigwaitinfo, SIGUSR1}, { - test_unmasked_matching, my_sigwaitinfo, SIGUSR1}, { - test_masked_matching, my_sigwaitinfo, SIGUSR1}, { - test_unmasked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, { - test_masked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, { - test_bad_address, my_sigwaitinfo, SIGUSR1}, { - test_bad_address2, my_sigwaitinfo, SIGUSR1}, -#endif -#if defined TEST_SIGTIMEDWAIT - { - test_empty_set, my_sigtimedwait, SIGUSR1}, { - test_unmasked_matching, my_sigtimedwait, SIGUSR1}, { - test_masked_matching, my_sigtimedwait, SIGUSR1}, { - test_unmasked_matching_noinfo, my_sigtimedwait, SIGUSR1}, { - test_masked_matching_noinfo, my_sigtimedwait, SIGUSR1}, { - test_bad_address, my_sigtimedwait, SIGUSR1}, { - test_bad_address2, my_sigtimedwait, SIGUSR1}, { - test_bad_address3, my_sigtimedwait, SIGUSR1}, { - test_timeout, my_sigtimedwait, 0}, -#endif -}; - -static struct test_variants { - swi_func swi; - enum tst_ts_type type; - char *desc; -} variants[] = { -#ifdef TEST_RT_SIGTIMEDWAIT - -#if (__NR_rt_sigtimedwait != __LTP__NR_INVALID_SYSCALL) - { .swi = my_rt_sigtimedwait, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"}, -#endif - -#if (__NR_rt_sigtimedwait_time64 != __LTP__NR_INVALID_SYSCALL) - { .swi = my_rt_sigtimedwait_time64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"}, -#endif - -#else /* !TEST_RT_SIGTIMEDWAIT */ - - { .swi = NULL, .type = TST_LIBC_TIMESPEC, .desc = "syscall with libc spec"}, - -#endif /* TEST_RT_SIGTIMEDWAIT */ +struct sigwait_test_desc tests[] = { + { test_empty_set, SIGUSR1}, + { test_unmasked_matching, SIGUSR1}, + { test_masked_matching, SIGUSR1}, + { test_unmasked_matching_noinfo, SIGUSR1}, + { test_masked_matching_noinfo, SIGUSR1}, + { test_bad_address, SIGUSR1}, + { test_bad_address2, SIGUSR1}, }; static void run(unsigned int i) { - struct test_variants *tv = &variants[tst_variant]; - struct test_desc *tc = &tests[i]; - swi_func swi; - - swi = tv->swi ? tv->swi : tc->swi; + struct sigwait_test_desc *tc = &tests[i]; - tc->tf(swi, tc->signo, tv->type); -} - -static void setup(void) -{ - tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc); - - signal(SIGUSR1, empty_handler); - signal(SIGALRM, empty_handler); - signal(SIGUSR2, SIG_IGN); - - alarm(10); /* arrange a 10 second timeout */ -} - -static void cleanup(void) -{ - alarm(0); + tc->tf(my_sigwaitinfo, tc->signo, TST_LIBC_TIMESPEC); } static struct tst_test test = { .test= run, .tcnt = ARRAY_SIZE(tests), - .test_variants = ARRAY_SIZE(variants), - .setup = setup, - .cleanup = cleanup, + .setup = sigwait_setup, + .cleanup = sigwait_cleanup, .forks_child = 1, };