Merge pull request #27843 from yuwata/usleep_safe

time-util: introduce usleep_safe()
This commit is contained in:
Lennart Poettering
2023-06-23 23:03:15 +02:00
committed by GitHub
22 changed files with 80 additions and 60 deletions
+17 -23
View File
@@ -33,12 +33,6 @@ static void set_alarm(usec_t usecs) {
assert_se(setitimer(ITIMER_REAL, &v, NULL) >= 0);
}
static void sleep_for(usec_t usecs) {
/* stupid usleep() might fail if >1000000 */
assert_se(usecs < USEC_PER_SEC);
usleep(usecs);
}
#define TEST_BARRIER(_FUNCTION, _CHILD_CODE, _WAIT_CHILD, _PARENT_CODE, _WAIT_PARENT) \
TEST(_FUNCTION) { \
Barrier b = BARRIER_NULL; \
@@ -94,9 +88,9 @@ static void sleep_for(usec_t usecs) {
/*
* Test basic sync points
* This places a barrier in both processes and waits synchronously for them.
* The timeout makes sure the sync works as expected. The sleep_for() on one side
* The timeout makes sure the sync works as expected. The usleep_safe() on one side
* makes sure the exit of the parent does not overwrite previous barriers. Due
* to the sleep_for(), we know that the parent already exited, thus there's a
* to the usleep_safe(), we know that the parent already exited, thus there's a
* pending HUP on the pipe. However, the barrier_sync() prefers reads on the
* eventfd, thus we can safely wait on the barrier.
*/
@@ -104,7 +98,7 @@ TEST_BARRIER(barrier_sync,
({
set_alarm(BASE_TIME * 10);
assert_se(barrier_place(&b));
sleep_for(BASE_TIME * 2);
usleep_safe(BASE_TIME * 2);
assert_se(barrier_sync(&b));
}),
TEST_BARRIER_WAIT_SUCCESS(pid1),
@@ -124,7 +118,7 @@ TEST_BARRIER(barrier_sync,
*/
TEST_BARRIER(barrier_wait_next,
({
sleep_for(BASE_TIME);
usleep_safe(BASE_TIME);
set_alarm(BASE_TIME * 10);
assert_se(barrier_wait_next(&b));
assert_se(barrier_place(&b));
@@ -150,7 +144,7 @@ TEST_BARRIER(barrier_wait_next,
*/
TEST_BARRIER(barrier_wait_next_twice,
({
sleep_for(BASE_TIME);
usleep_safe(BASE_TIME);
set_alarm(BASE_TIME);
assert_se(barrier_wait_next(&b));
assert_se(barrier_wait_next(&b));
@@ -161,7 +155,7 @@ TEST_BARRIER(barrier_wait_next_twice,
set_alarm(BASE_TIME * 10);
assert_se(barrier_place(&b));
assert_se(barrier_place(&b));
sleep_for(BASE_TIME * 4);
usleep_safe(BASE_TIME * 4);
}),
TEST_BARRIER_WAIT_SUCCESS(pid2));
@@ -173,7 +167,7 @@ TEST_BARRIER(barrier_wait_next_twice,
*/
TEST_BARRIER(barrier_wait_next_twice_local,
({
sleep_for(BASE_TIME);
usleep_safe(BASE_TIME);
set_alarm(BASE_TIME);
assert_se(barrier_wait_next(&b));
assert_se(barrier_place(&b));
@@ -186,7 +180,7 @@ TEST_BARRIER(barrier_wait_next_twice_local,
set_alarm(BASE_TIME * 10);
assert_se(barrier_place(&b));
assert_se(barrier_place(&b));
sleep_for(BASE_TIME * 4);
usleep_safe(BASE_TIME * 4);
}),
TEST_BARRIER_WAIT_SUCCESS(pid2));
@@ -198,7 +192,7 @@ TEST_BARRIER(barrier_wait_next_twice_local,
*/
TEST_BARRIER(barrier_wait_next_twice_sync,
({
sleep_for(BASE_TIME);
usleep_safe(BASE_TIME);
set_alarm(BASE_TIME);
assert_se(barrier_wait_next(&b));
assert_se(barrier_sync_next(&b));
@@ -219,7 +213,7 @@ TEST_BARRIER(barrier_wait_next_twice_sync,
*/
TEST_BARRIER(barrier_wait_next_twice_local_sync,
({
sleep_for(BASE_TIME);
usleep_safe(BASE_TIME);
set_alarm(BASE_TIME);
assert_se(barrier_wait_next(&b));
assert_se(barrier_place(&b));
@@ -253,7 +247,7 @@ TEST_BARRIER(barrier_sync_next,
TEST_BARRIER_WAIT_SUCCESS(pid1),
({
set_alarm(BASE_TIME * 10);
sleep_for(BASE_TIME);
usleep_safe(BASE_TIME);
assert_se(barrier_place(&b));
assert_se(barrier_place(&b));
assert_se(barrier_sync(&b));
@@ -274,7 +268,7 @@ TEST_BARRIER(barrier_sync_next_local,
}),
TEST_BARRIER_WAIT_ALARM(pid1),
({
sleep_for(BASE_TIME * 2);
usleep_safe(BASE_TIME * 2);
}),
TEST_BARRIER_WAIT_SUCCESS(pid2));
@@ -323,7 +317,7 @@ TEST_BARRIER(barrier_wait_abortion_unmatched,
}),
TEST_BARRIER_WAIT_ALARM(pid1),
({
sleep_for(BASE_TIME * 2);
usleep_safe(BASE_TIME * 2);
}),
TEST_BARRIER_WAIT_SUCCESS(pid2));
@@ -356,7 +350,7 @@ TEST_BARRIER(barrier_wait_abortion_local_unmatched,
}),
TEST_BARRIER_WAIT_ALARM(pid1),
({
sleep_for(BASE_TIME * 2);
usleep_safe(BASE_TIME * 2);
}),
TEST_BARRIER_WAIT_SUCCESS(pid2));
@@ -379,12 +373,12 @@ TEST_BARRIER(barrier_exit,
/*
* Test child exit with sleep
* Same as test_barrier_exit but verifies the test really works due to the
* child-exit. We add a usleep() which triggers the alarm in the parent and
* child-exit. We add a usleep_safe() which triggers the alarm in the parent and
* causes the test to time out.
*/
TEST_BARRIER(barrier_no_exit,
({
sleep_for(BASE_TIME * 2);
usleep_safe(BASE_TIME * 2);
}),
TEST_BARRIER_WAIT_SUCCESS(pid1),
({
@@ -407,7 +401,7 @@ TEST_BARRIER(barrier_no_exit,
TEST_BARRIER(barrier_pending_exit,
({
set_alarm(BASE_TIME * 4);
sleep_for(BASE_TIME * 2);
usleep_safe(BASE_TIME * 2);
assert_se(barrier_wait_next(&b));
assert_se(barrier_sync_next(&b));
assert_se(barrier_place(&b));
+5 -5
View File
@@ -31,27 +31,27 @@ int main(int argc, char *argv[]) {
sd_notify(0,
"STATUS=Starting up");
usleep(duration);
usleep_safe(duration);
sd_notify(0,
"STATUS=Running\n"
"READY=1");
usleep(duration);
usleep_safe(duration);
sd_notify(0,
"STATUS=Reloading\n"
"RELOADING=1");
usleep(duration);
usleep_safe(duration);
sd_notify(0,
"STATUS=Running\n"
"READY=1");
usleep(duration);
usleep_safe(duration);
sd_notify(0,
"STATUS=Quitting\n"
"STOPPING=1");
usleep(duration);
usleep_safe(duration);
return EXIT_SUCCESS;
}
+1 -1
View File
@@ -740,7 +740,7 @@ TEST(xopenat_lock) {
* little and assume that's enough time for the child process to get along far enough. It doesn't
* matter if it doesn't get far enough, in that case we just won't trigger the fallback logic in
* xopenat_lock(), but the test will still succeed. */
assert_se(usleep(20 * USEC_PER_MSEC) >= 0);
assert_se(usleep_safe(20 * USEC_PER_MSEC) >= 0);
assert_se(unlinkat(tfd, "abc", AT_REMOVEDIR) >= 0);
fd = safe_close(fd);
+3 -3
View File
@@ -30,11 +30,11 @@ static void *fake_pressure_thread(void *p) {
_cleanup_free_ struct fake_pressure_context *c = ASSERT_PTR(p);
_cleanup_close_ int cfd = -EBADF;
usleep(150);
usleep_safe(150);
assert_se(write(c->fifo_fd, &(const char) { 'x' }, 1) == 1);
usleep(150);
usleep_safe(150);
cfd = accept4(c->socket_fd, NULL, NULL, SOCK_CLOEXEC);
assert_se(cfd >= 0);
@@ -164,7 +164,7 @@ _noreturn_ static void real_pressure_eat_memory(int pipe_fd) {
log_info("Ate %s in total.", FORMAT_BYTES(ate));
usleep(50 * USEC_PER_MSEC);
usleep_safe(50 * USEC_PER_MSEC);
}
}
+1 -1
View File
@@ -638,7 +638,7 @@ TEST(safe_fork) {
if (r == 0) {
/* child */
usleep(100 * USEC_PER_MSEC);
usleep_safe(100 * USEC_PER_MSEC);
_exit(88);
}
+20 -2
View File
@@ -3,8 +3,9 @@
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/types.h>
#define __STDC_WANT_IEC_60559_TYPES_EXT__
#include <float.h>
@@ -28,6 +29,18 @@ DISABLE_WARNING_TYPE_LIMITS;
(t)-1 < (t)0 ? ", signed" : ", unsigned", \
alignof(t))
#define check_no_sign(t, size) \
do { \
info_no_sign(t); \
assert_se(sizeof(t) == size); \
} while (false)
#define check(t, size) \
do { \
info(t); \
assert_se(sizeof(t) == size); \
} while (false)
enum Enum {
enum_value,
};
@@ -44,6 +57,12 @@ enum BigEnum2 {
int main(void) {
int (*function_pointer)(void);
check_no_sign(dev_t, SIZEOF_DEV_T);
check_no_sign(ino_t, SIZEOF_INO_T);
check_no_sign(rlim_t, SIZEOF_RLIM_T);
check(time_t, SIZEOF_TIME_T);
check(typeof(((struct timex *)0)->freq), SIZEOF_TIMEX_MEMBER);
info_no_sign(typeof(function_pointer));
info_no_sign(void*);
info(char*);
@@ -76,7 +95,6 @@ int main(void) {
info(size_t);
info(ssize_t);
info(time_t);
info(usec_t);
#ifdef __GLIBC__
info(__time_t);
+1 -1
View File
@@ -29,7 +29,7 @@ int main(int argc, char *argv[]) {
for (i = 0; i < count; i++) {
t = watchdog_runtime_wait();
log_info("Sleeping " USEC_FMT " microseconds...", t);
usleep(t);
usleep_safe(t);
log_info("Pinging...");
r = watchdog_ping();
if (r < 0)
+1 -1
View File
@@ -130,7 +130,7 @@ static int run(int argc, char *argv[]) {
r = safe_atou(argv[3], &us);
if (r < 0)
return log_error_errno(r, "Invalid delay '%s': %m", argv[3]);
usleep(us);
usleep_safe(us);
}
assert_se(udev_rules_load(&rules, RESOLVE_NAME_EARLY) == 0);