]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Implement reliable sleep functions i_sleep*_usecs(), i_sleep*_msecs(), and i_sle...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Thu, 13 Dec 2018 09:06:17 +0000 (10:06 +0100)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Tue, 10 Sep 2019 07:01:46 +0000 (10:01 +0300)
Versions with and without support for being interrupted by signals are available.

src/lib/Makefile.am
src/lib/sleep.c [new file with mode: 0644]
src/lib/sleep.h [new file with mode: 0644]

index 3226e3670a7ea3aedd539867f42a59c600dd5c9e..ffed17f79badfb76afe7548237fd3df54d9be17e 100644 (file)
@@ -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 (file)
index 0000000..7b3b6fa
--- /dev/null
@@ -0,0 +1,74 @@
+/* Copyright (c) 2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "sleep.h"
+
+#include <time.h>
+
+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 (file)
index 0000000..0f8d7c3
--- /dev/null
@@ -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