From nobody Mon Feb 9 01:46:31 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9521CC7EE29 for ; Tue, 6 Jun 2023 14:37:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238038AbjFFOhp (ORCPT ); Tue, 6 Jun 2023 10:37:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41340 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237497AbjFFOhb (ORCPT ); Tue, 6 Jun 2023 10:37:31 -0400 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D465710E0 for ; Tue, 6 Jun 2023 07:37:26 -0700 (PDT) Message-ID: <20230606142031.246358079@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1686062245; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: references:references; bh=dCkKva35ZSsZYYHSJnYJ6h+ag01NecWv1M8cjMvd9xA=; b=QU/albRfnjNxtVaW4ks6OeYpS1Ry45BwaI5jS+HjFYb2u9gZDXAtypmNiWbcV65qkRyqjL HkO3FnDqbvQNrM2SS2t0J90ZBR0/kwI5aVuDtjPm0vp5kifLJwelmPtGbeekDoXQdVQVNg 6gzmA7A68rL0e05W+bxbYJexIfYLw7n+FqSlykA/BLTUIxqYLyKs9izoFlPR/TiP21srSF oOIObNNB7TCW8ZY2MfwOO7aNETXuW6va+/WD30jSYAPTqvxjxkGIFlXmdYNV3FpLVsUSlV pukYPDRopj0hHXsVKgTk1qbdJsRoXds9OHOlfTT5kO+QzmetKchG3vX569dxGQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1686062245; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: references:references; bh=dCkKva35ZSsZYYHSJnYJ6h+ag01NecWv1M8cjMvd9xA=; b=sBlw+8T1RUYJw2yek8bJMo4AxLnoh2lL8sCOe8xz95+a/RPwM6Jv3KHDRF4SYEMEOouBcZ Z5jUQsDF7OSaohBg== From: Thomas Gleixner To: LKML Cc: Frederic Weisbecker , Anna-Maria Behnsen , John Stultz , Peter Zijlstra , Ingo Molnar , Stephen Boyd , Eric Biederman , Oleg Nesterov Subject: [patch 04/45] selftests/timers/posix_timers: Validate signal rules References: <20230606132949.068951363@linutronix.de> MIME-Version: 1.0 Date: Tue, 6 Jun 2023 16:37:25 +0200 (CEST) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a test case to validate correct behaviour vs. timer reprogramming and deletion. The handling of queued signals in case of timer reprogramming or deletion is inconsistent at best. POSIX does not really specify the behaviour for that: - "The effect of disarming or resetting a timer with pending expiration notifications is unspecified." - "The disposition of pending signals for the deleted timer is unspecified." In both cases it is reasonable to expect that pending signals are discarded. Especially in the reprogramming case it does not make sense to account for previous overruns or to deliver a signal for a timer which has been disarmed. Add tests to validate that no unexpected signals are delivered. They fail for now until the signal and posix timer code is updated. Signed-off-by: Thomas Gleixner --- tools/testing/selftests/timers/posix_timers.c | 113 +++++++++++++++++++++= ++++- 1 file changed, 112 insertions(+), 1 deletion(-) --- a/tools/testing/selftests/timers/posix_timers.c +++ b/tools/testing/selftests/timers/posix_timers.c @@ -363,10 +363,119 @@ static void check_sig_ign(int thread) } } =20 +static void check_rearm(void) +{ + struct tmrsig tsig =3D { }; + struct itimerspec its; + struct sigaction sa; + struct sigevent sev; + timer_t timerid; + sigset_t set; + + sa.sa_flags =3D SA_SIGINFO; + sa.sa_sigaction =3D siginfo_handler; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGUSR1, &sa, NULL)) + fatal_error(NULL, "sigaction()"); + + /* Block the signal */ + sigemptyset(&set); + sigaddset(&set, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &set, NULL)) + fatal_error(NULL, "sigprocmask(SIG_BLOCK)"); + + memset(&sev, 0, sizeof(sev)); + sev.sigev_notify =3D SIGEV_SIGNAL; + sev.sigev_signo =3D SIGUSR1; + sev.sigev_value.sival_ptr =3D &tsig; + + if (timer_create(CLOCK_MONOTONIC, &sev, &timerid)) + fatal_error(NULL, "timer_create()"); + + /* Start the timer to expire in 100ms and 100ms intervals */ + its.it_value.tv_sec =3D 0; + its.it_value.tv_nsec =3D 100000000; + its.it_interval.tv_sec =3D 0; + its.it_interval.tv_nsec =3D 100000000; + timer_settime(timerid, 0, &its, NULL); + + sleep(1); + + /* Reprogram the timer to single shot */ + its.it_value.tv_sec =3D 1; + its.it_value.tv_nsec =3D 0; + its.it_interval.tv_sec =3D 0; + its.it_interval.tv_nsec =3D 0; + timer_settime(timerid, 0, &its, NULL); + + /* Unblock it, which should not deliver a signal */ + if (sigprocmask(SIG_UNBLOCK, &set, NULL)) + fatal_error(NULL, "sigprocmask(SIG_UNBLOCK)"); + + if (timer_delete(timerid)) + fatal_error(NULL, "timer_delete()"); + + if (!tsig.signals) + ksft_test_result_pass("check_rearm\n"); + else + ksft_test_result_fail("check_rearm\n"); +} + +static void check_delete(void) +{ + struct tmrsig tsig =3D { }; + struct itimerspec its; + struct sigaction sa; + struct sigevent sev; + timer_t timerid; + sigset_t set; + + sa.sa_flags =3D SA_SIGINFO; + sa.sa_sigaction =3D siginfo_handler; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGUSR1, &sa, NULL)) + fatal_error(NULL, "sigaction()"); + + /* Block the signal */ + sigemptyset(&set); + sigaddset(&set, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &set, NULL)) + fatal_error(NULL, "sigprocmask(SIG_BLOCK)"); + + memset(&sev, 0, sizeof(sev)); + sev.sigev_notify =3D SIGEV_SIGNAL; + sev.sigev_signo =3D SIGUSR1; + sev.sigev_value.sival_ptr =3D &tsig; + + if (timer_create(CLOCK_MONOTONIC, &sev, &timerid)) + fatal_error(NULL, "timer_create()"); + + /* Start the timer to expire in 100ms and 100ms intervals */ + its.it_value.tv_sec =3D 0; + its.it_value.tv_nsec =3D 100000000; + its.it_interval.tv_sec =3D 0; + its.it_interval.tv_nsec =3D 100000000; + timer_settime(timerid, 0, &its, NULL); + + sleep(1); + + if (timer_delete(timerid)) + fatal_error(NULL, "timer_delete()"); + + /* Unblock it, which should not deliver a signal */ + if (sigprocmask(SIG_UNBLOCK, &set, NULL)) + fatal_error(NULL, "sigprocmask(SIG_UNBLOCK)"); + + if (!tsig.signals) + ksft_test_result_pass("check_delete\n"); + else + ksft_test_result_fail("check_delete\n"); +} + int main(int argc, char **argv) { ksft_print_header(); - ksft_set_plan(8); + ksft_set_plan(10); =20 check_itimer(ITIMER_VIRTUAL, "ITIMER_VIRTUAL"); check_itimer(ITIMER_PROF, "ITIMER_PROF"); @@ -386,6 +495,8 @@ int main(int argc, char **argv) check_timer_distribution(); check_sig_ign(0); check_sig_ign(1); + check_rearm(); + check_delete(); =20 ksft_finished(); }