[LTP] [PATCH v4] openposix: timers/twoevtimers: Wait for both timer signals
Jan Stancek
jstancek@redhat.com
Mon Oct 12 10:03:50 CEST 2026
The test arms two timers with the same absolute expiration time and
then does a single sleep() before checking that both signals arrived.
sleep() returns as soon as the first signal interrupts it, and the
kernel delivers the two signals one at a time. This sporadically
leads to failure:
Caught abort signal
Test FAILED
even though the second timer fires microseconds later.
Make the counters volatile sig_atomic_t and move the printf() calls
out of the signal handlers, so that they only touch the counters and
cannot clobber errno behind nanosleep()'s back.
Arm the timers to expire 50ms from now instead of 3 seconds, so the test
passes in about 50ms, and lower LONGTIME, the upper bound for when a
signal does not arrive, from 5 to 3 seconds. Also correct the header
comment: the timers live in the same process, not in different
processes, and the test only checks that both of them expire, not that
they expire at the same time.
Signed-off-by: Jan Stancek <jstancek@redhat.com>
---
.../functional/timers/timers/twoevtimers.c | 58 ++++++++++++++-----
1 file changed, 44 insertions(+), 14 deletions(-)
Changes in v4:
- sleep in 50ms chunks
diff --git a/testcases/open_posix_testsuite/functional/timers/timers/twoevtimers.c b/testcases/open_posix_testsuite/functional/timers/timers/twoevtimers.c
index 0e46229777fe..2bc819721fd5 100644
--- a/testcases/open_posix_testsuite/functional/timers/timers/twoevtimers.c
+++ b/testcases/open_posix_testsuite/functional/timers/timers/twoevtimers.c
@@ -5,35 +5,43 @@
* of this license, see the COPYING file at the top level of this
* source tree.
*
- * Test having two timers in different processes set to expire at the
- * same time, and ensure they both expire at the same time.
+ * Test having two timers in the same process, armed with the same
+ * absolute expiration time but delivering different signals, and ensure
+ * that both of them expire.
+ *
+ * Note that the test does not (and cannot) verify that the two signals
+ * are delivered simultaneously. Signals are delivered one at a time, so
+ * the second one may still be on its way when the first one arrives.
+ * Poll for both of them in short sleeps until LONGTIME elapses.
*/
+#include <errno.h>
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <unistd.h>
#include "posixtest.h"
+#include "timespec.h"
-#define EXPIREDELTA 3
-#define LONGTIME 5
+#define EXPIREDELTA_NS 50000000
+#define LONGTIME 3
+
+#define POLL_MS 50
+#define POLL_COUNT (LONGTIME * 1000 / POLL_MS)
#define CHILDPASS 1
-static int caughtabort = 0;
-static int caughtalarm = 0;
+static volatile sig_atomic_t caughtabort = 0;
+static volatile sig_atomic_t caughtalarm = 0;
-static void handler_abrt(int signo)
+static void handler_abrt(int signo PTS_ATTRIBUTE_UNUSED)
{
- printf("Caught abort signal\n");
caughtabort++;
}
-static void handler_alrm(int signo)
+static void handler_alrm(int signo PTS_ATTRIBUTE_UNUSED)
{
- printf("Caught alarm signal\n");
caughtalarm++;
}
@@ -45,6 +53,8 @@ int test_main(int argc, char **argv)
struct timespec ts;
struct itimerspec its;
int flags = 0;
+ struct timespec poll_ts = { .tv_nsec = POLL_MS * 1000000 };
+ int i;
act1.sa_handler = handler_abrt;
act1.sa_flags = 0;
@@ -77,8 +87,12 @@ int test_main(int argc, char **argv)
return PTS_UNRESOLVED;
}
- its.it_value.tv_sec = ts.tv_sec + EXPIREDELTA;
- its.it_value.tv_nsec = ts.tv_nsec;
+ its.it_value.tv_sec = ts.tv_sec;
+ its.it_value.tv_nsec = ts.tv_nsec + EXPIREDELTA_NS;
+ if (its.it_value.tv_nsec >= NSEC_IN_SEC) {
+ its.it_value.tv_sec++;
+ its.it_value.tv_nsec -= NSEC_IN_SEC;
+ }
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
@@ -93,7 +107,23 @@ int test_main(int argc, char **argv)
return PTS_UNRESOLVED;
}
- sleep(EXPIREDELTA + 1);
+ /*
+ * Sleep in short chunks rather than once for LONGTIME: a signal
+ * that lands between the check and nanosleep() has nothing to
+ * interrupt, so a single long sleep would run out the whole budget.
+ * A chunk cut short by a signal only brings the next check forward.
+ */
+ for (i = 0; i < POLL_COUNT && !(caughtalarm && caughtabort); i++) {
+ if (nanosleep(&poll_ts, NULL) != 0 && errno != EINTR) {
+ perror("nanosleep() did not return success");
+ return PTS_UNRESOLVED;
+ }
+ }
+
+ if (caughtabort)
+ printf("Caught abort signal\n");
+ if (caughtalarm)
+ printf("Caught alarm signal\n");
if ((caughtalarm == 1) && (caughtabort == 1)) {
printf("Test PASSED\n");
--
2.56.0
More information about the ltp
mailing list