From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL autolearn=ham autolearn_force=no version=3.4.4 Received: from second.openwall.net (second.openwall.net [193.110.157.125]) by inbox.vuxu.org (Postfix) with SMTP id 29B1E22445 for ; Tue, 5 Nov 2024 23:45:34 +0100 (CET) Received: (qmail 5425 invoked by uid 550); 5 Nov 2024 22:45:19 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com x-ms-reactions: disallow Received: (qmail 5284 invoked from network); 5 Nov 2024 22:45:18 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=boeing.com; s=boeing-s1912; t=1730846709; bh=gldswJ3aZ2R/nssnb5oqkdUJebD4/uByPojn8zdY8yM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t9TfGZDcc1Sxx+dssVoemNWQsdiueYJ/OHJLuXkBbNwve5SwiW5UFZNCuodmzzTnO KGsdQIx0s0/oC9BvfYDGm2yzx46vP7IY1KR40UXSlxSEb9fZPLpddgdSigofcQ3ULA 5GMZPD7S+immrrGC0QSyNfBe/nkYccAN/kHd90TtE42dnk/7LEqzgrEUsIMOyEBdNd FO4KiTUXrv7YGmdB3rUuw2ezP1lKzH/EtqnWMGLcIWWSoWAk2Jq9AQPwhU40LMU6YM Do3/AY+WVve8/69X5NoTynz9tl4IiO5qtgpzwFm3Ju4Bkse+DW2pE3yMZJAjOiEwYO MIzj71zsBfIdQ== From: Ryan Gardner To: musl@lists.openwall.com Cc: Ryan Ward Date: Tue, 5 Nov 2024 22:44:36 +0000 Message-Id: <20241105224437.67-2-ryan.p.gardner@boeing.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241105224437.67-1-ryan.p.gardner@boeing.com> References: <20241105224437.67-1-ryan.p.gardner@boeing.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-TM-AS-GCONF: 00 Subject: [musl] [PATCH 2/3 libc-test] functional:time:timer_delete test From: Ryan Ward Testing of the musl API against the POSIX 2008 standard, which has removed the requirement for returning EINVAL upon receiving an invalid timer_id, and simply classifies it as undefined behavior. Tests added: - Deleting an unarmed timer - Deleting an armed timer - Deleting a timer that has been passed in the SIGEV_THREAD flag - Deleting a completed timer - Deleting, recreating, and deleting a timer References: - https://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_delete.html Signed-off-by: Ryan Ward --- src/functional/timer_delete.c | 123 ++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/functional/timer_delete.c diff --git a/src/functional/timer_delete.c b/src/functional/timer_delete.c new file mode 100644 index 0000000..810a4d1 --- /dev/null +++ b/src/functional/timer_delete.c @@ -0,0 +1,123 @@ +/* + * timer_delete.c unit test + */ +#include "test.h" +#include +#include +#include +#include +#include +#include + +#define TEST(c, ...) ((c) || (t_error(#c " failed: " __VA_ARGS__), 0)) + +#define SLEEP_NANO 500000 +#define TIMER_SPEC \ + (struct itimerspec) \ + { \ + .it_value = {0, SLEEP_NANO}, .it_interval = { 0, 0 } \ + } + +typedef struct { + clockid_t clock; + int armed; +} timer_params; + +static void dummy_signal_handler(int signum) {} + +static void delete_timer(const timer_params *timer) +{ + timer_t timer_id = 0; + if (timer_create(timer->clock, NULL, &timer_id) < 0) { + t_error("Failed to created SIGEV_SIGNAL timer: %s\n", strerror(errno)); + return; + } + + if (timer->armed) { + if (timer_settime(timer_id, 0, &TIMER_SPEC, NULL) < 0) { + t_error("Failed to arm SIGEV_SIGNAL timer: %s\n", strerror(errno)); + } + } + + TEST(timer_delete(timer_id) == 0, + "Failed to delete SIGEV_SIGNAL timer: %d\n", timer_id); +} + +static void delete_thread_timer(const timer_params *timer) +{ + timer_t timer_id = 0; + struct sigevent sigev = {.sigev_signo = SIGRTMIN, + .sigev_notify = SIGEV_THREAD}; + + if (timer_create(timer->clock, &sigev, &timer_id) < 0) { + t_error("Failed to create SIGEV_THREAD timer: %s\n", strerror(errno)); + return; + } + + if (timer->armed) { + if (timer_settime(timer_id, 0, &TIMER_SPEC, NULL) < 0) { + t_error("Failed to arm SIGEV_THREAD timer: %s\n", strerror(errno)); + } + } + + TEST(timer_delete(timer_id) == 0, + "Failed to delete SIGEV_THREAD timer: %d\n", timer_id); +} + +static void delete_completed_timer(timer_t timer_id, clockid_t clock) +{ + struct sigaction sa = {.sa_handler = dummy_signal_handler}; + + sigemptyset(&sa.sa_mask); + if (sigaction(SIGALRM, &sa, NULL) == -1) { + t_error("Error setting up signal handler: %s\n", strerror(errno)); + return; + } + + if (timer_create(clock, NULL, &timer_id) < 0) { + t_error("Failed to created SIGEV_SIGNAL timer: %s\n", strerror(errno)); + return; + } + + if (timer_settime(timer_id, 0, &TIMER_SPEC, NULL) < 0) { + t_error("Failed to arm SIGEV_SIGNAL timer: %s\n", strerror(errno)); + } + + // Wait for SIGARLM + pause(); + + TEST(timer_delete(timer_id) == 0, + "Failed to delete SIGEV_SIGNAL timer: %d\n", timer_id); +} + +int main(void) +{ + static const clockid_t clocks_to_test[] = {CLOCK_REALTIME, CLOCK_MONOTONIC}; + static const size_t num_clocks = + sizeof(clocks_to_test) / sizeof(*clocks_to_test); + + for (int clock = 0; clock < num_clocks; ++clock) { + const timer_params unarmed_timer = {0, clocks_to_test[clock]}; + const timer_params armed_timer = {1, clocks_to_test[clock]}; + // Delete an unarmed timer + delete_timer(&unarmed_timer); + + // Delete an armed timer + delete_timer(&armed_timer); + + // Delete a thread unarmed timer + delete_thread_timer(&unarmed_timer); + + // Delete a thread armed timer + delete_thread_timer(&armed_timer); + + // Let the timer run out, and delete + timer_t timer_id = 0; + delete_completed_timer(timer_id, clocks_to_test[clock]); + + // Retry the same operation with the same timer_id (should succeed) + delete_completed_timer(timer_id, clocks_to_test[clock]); + } + + return t_status; +} -- 2.34.1