From: Stephan Bosch Date: Thu, 13 Dec 2018 09:06:17 +0000 (+0100) Subject: lib: Implement reliable sleep functions i_sleep*_usecs(), i_sleep*_msecs(), and i_sle... X-Git-Tag: 2.3.8~207 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e5c2788b0a19ac1b090b0925fb8125d8fe0f1235;p=thirdparty%2Fdovecot%2Fcore.git lib: Implement reliable sleep functions i_sleep*_usecs(), i_sleep*_msecs(), and i_sleep*_secs(). Versions with and without support for being interrupted by signals are available. --- diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 3226e3670a..ffed17f79b 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -145,6 +145,7 @@ liblib_la_SOURCES = \ sha1.c \ sha2.c \ sha3.c \ + sleep.c \ sort.c \ stats-dist.c \ str.c \ @@ -299,6 +300,7 @@ headers = \ sha1.h \ sha2.h \ sha3.h \ + sleep.h \ sort.h \ stats-dist.h \ str.h \ diff --git a/src/lib/sleep.c b/src/lib/sleep.c new file mode 100644 index 0000000000..7b3b6fa911 --- /dev/null +++ b/src/lib/sleep.c @@ -0,0 +1,74 @@ +/* Copyright (c) 2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "sleep.h" + +#include + +static bool ATTR_NOWARN_UNUSED_RESULT +sleep_timespec(const struct timespec *ts_sleep, bool interruptible) +{ + struct timespec ts_remain = *ts_sleep; + + while (nanosleep(&ts_remain, &ts_remain) < 0) { + if (errno != EINTR) + i_fatal("nanosleep(): %m"); + if (interruptible) + return FALSE; + } + return TRUE; +} + +void i_sleep_usecs(unsigned long long usecs) +{ + struct timespec ts_sleep; + + ts_sleep.tv_sec = (time_t)(usecs / 1000000); + ts_sleep.tv_nsec = (long)(usecs % 1000000) * 1000; + sleep_timespec(&ts_sleep, FALSE); +} + +void i_sleep_msecs(unsigned int msecs) +{ + struct timespec ts_sleep; + + ts_sleep.tv_sec = (time_t)(msecs / 1000); + ts_sleep.tv_nsec = (long)(msecs % 1000) * 1000000; + sleep_timespec(&ts_sleep, FALSE); +} + +void i_sleep_secs(time_t secs) +{ + struct timespec ts_sleep; + + ts_sleep.tv_sec = secs; + ts_sleep.tv_nsec = 0; + sleep_timespec(&ts_sleep, FALSE); +} + +bool i_sleep_intr_usecs(unsigned long long usecs) +{ + struct timespec ts_sleep; + + ts_sleep.tv_sec = (time_t)(usecs / 1000000); + ts_sleep.tv_nsec = (long)(usecs % 1000000) * 1000; + return sleep_timespec(&ts_sleep, TRUE); +} + +bool i_sleep_intr_msecs(unsigned int msecs) +{ + struct timespec ts_sleep; + + ts_sleep.tv_sec = (time_t)(msecs / 1000); + ts_sleep.tv_nsec = (long)(msecs % 1000) * 1000000; + return sleep_timespec(&ts_sleep, TRUE); +} + +bool i_sleep_intr_secs(time_t secs) +{ + struct timespec ts_sleep; + + ts_sleep.tv_sec = secs; + ts_sleep.tv_nsec = 0; + return sleep_timespec(&ts_sleep, TRUE); +} diff --git a/src/lib/sleep.h b/src/lib/sleep.h new file mode 100644 index 0000000000..0f8d7c30ca --- /dev/null +++ b/src/lib/sleep.h @@ -0,0 +1,30 @@ +#ifndef SLEEP_H +#define SLEEP_H + +/* Sleep for the indicated number of microseconds. Signal interruptions are + handled and ignored internally. */ +void i_sleep_usecs(unsigned long long usecs); +/* Sleep for the indicated number of milliseconds. Signal interruptions are + handled and ignored internally. */ +void i_sleep_msecs(unsigned int msecs); +/* Sleep for the indicated number of seconds. Signal interruptions are + handled and ignored internally. */ +void i_sleep_secs(time_t secs); + +/* Sleep for the indicated number of microseconds while allowing signal + interruptions. This function returns FALSE when it is interrupted by a + signal. Otherwise, this function always returns TRUE. */ +bool ATTR_NOWARN_UNUSED_RESULT +i_sleep_intr_usecs(unsigned long long usecs); +/* Sleep for the indicated number of milliseconds while allowing signal + interruptions. This function returns FALSE when it is interrupted by a + signal. Otherwise, this function always returns TRUE. */ +bool ATTR_NOWARN_UNUSED_RESULT +i_sleep_intr_msecs(unsigned int msecs); +/* Sleep for the indicated number of seconds while allowing signal + interruptions. This function returns FALSE when it is interrupted by a + signal. Otherwise, this function always returns TRUE. */ +bool ATTR_NOWARN_UNUSED_RESULT +i_sleep_intr_secs(time_t secs); + +#endif