|
Message-Id: <20241105224437.67-2-ryan.p.gardner@boeing.com> Date: Tue, 5 Nov 2024 22:44:36 +0000 From: Ryan Gardner <ryan.p.gardner@...ing.com> To: musl@...ts.openwall.com Cc: Ryan Ward <ryan.c.ward3@...ing.com> Subject: [PATCH 2/3 libc-test] functional:time:timer_delete test From: Ryan Ward <ryan.c.ward3@...ing.com> 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 <ryan.c.ward3@...ing.com> --- 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 <errno.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#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
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.