summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2024-01-08 16:03:32 -0500
committerJakob Kaivo <jkk@ung.org>2024-01-08 16:03:32 -0500
commitfad5b725a63ea8bf369781ea24ba739584f2dfe0 (patch)
tree6a0430d63938f0d94957f3b8bdabfbc2e537dc90
parent44e872373e75bf291628ec81933562e579ca3398 (diff)
add macro to assert signal-safety of library functions
-rw-r--r--src/_assert.h60
-rw-r--r--src/_safety.h71
-rw-r--r--src/signal/__signal.c3
-rw-r--r--src/signal/_signal.h8
4 files changed, 83 insertions, 59 deletions
diff --git a/src/_assert.h b/src/_assert.h
index 2466455f..ef0de249 100644
--- a/src/_assert.h
+++ b/src/_assert.h
@@ -1,59 +1 @@
-#ifndef ___ASSERT_H__
-#define ___ASSERT_H__
-
-#include <errno.h>
-#include <stdio.h>
-#include "stdlib/_stdlib.h"
-
-#ifdef THREADS
-_Thread_local
-#endif
-extern struct __checked_call {
- char *file;
- char *func;
- unsigned long long line;
-} __checked_call;
-
-#ifndef NDEBUG
-#define ASSERT_NONNULL(__ptr) do { \
- if (!__ptr) { \
- struct __constraint_info _ci = {0}; \
- _ci.func = __func__; \
- __stdlib.constraint_handler("Undefined behavior: " \
- "Parameter " #__ptr " can not be NULL", &_ci, 0 /* was EFAULT */); \
- } \
-} while (0)
-
-#define ASSERT_NONZERO(__n) do { \
- if (!__n) { \
- struct __constraint_info _ci = {0}; \
- _ci.func = __func__; \
- __stdlib.constraint_handler("Undefined behavior: " \
- "Parameter " #__n " can not be 0", &_ci, ERANGE); \
- } \
-} while (0)
-
-#define ASSERT_NOOVERLAP(__x, __y, __s) do { \
- /* TODO */ \
-} while (0)
-
-#define ASSERT_REPRESENTABLE(_n, _min, _max, _type, _sentinel) do { \
- if (!(((_n) == (_sentinel)) || (((_min) <= (_n)) && ((_n) <= (_max))))) { \
- struct __constraint_info _ci = {0}; \
- _ci.func = __func__; \
- _ci.value = _n; \
- __stdlib.constraint_handler("Undefined behavior: " \
- "Parameter " #_n " must be representable as a " #_type \
- " or be equal to " #_sentinel, &_ci, ERANGE); \
- } \
- } while (0)
-#else
-
-#define ASSERT_REPRESENTABLE(_n, _min, _max, _type, _sentinel)
-#define ASSERT_NOOVERLAP(__x, __y, __s)
-#define ASSERT_NONNULL(x)
-#define ASSERT_NONZERO(n)
-
-#endif
-
-#endif
+#include "_safety.h"
diff --git a/src/_safety.h b/src/_safety.h
new file mode 100644
index 00000000..5fd70493
--- /dev/null
+++ b/src/_safety.h
@@ -0,0 +1,71 @@
+#ifndef ___ASSERT_H__
+#define ___ASSERT_H__
+
+#include <errno.h>
+#include <stdio.h>
+#include "stdlib/_stdlib.h"
+#include "signal/_signal.h"
+
+#if 0
+_Thread_local
+#endif
+extern struct __checked_call {
+ char *file;
+ char *func;
+ unsigned long long line;
+} __checked_call;
+
+#ifndef NDEBUG
+#define ASSERT_NONNULL(__ptr) do { \
+ if (!__ptr) { \
+ struct __constraint_info _ci = {0}; \
+ _ci.func = __func__; \
+ __stdlib.constraint_handler("Undefined behavior: " \
+ "Parameter " #__ptr " can not be NULL", &_ci, 0 /* was EFAULT */); \
+ } \
+} while (0)
+
+#define ASSERT_NONZERO(__n) do { \
+ if (!__n) { \
+ struct __constraint_info _ci = {0}; \
+ _ci.func = __func__; \
+ __stdlib.constraint_handler("Undefined behavior: " \
+ "Parameter " #__n " can not be 0", &_ci, ERANGE); \
+ } \
+} while (0)
+
+#define ASSERT_NOOVERLAP(__x, __y, __s) do { \
+ /* TODO */ \
+} while (0)
+
+#define ASSERT_REPRESENTABLE(_n, _min, _max, _type, _sentinel) do { \
+ if (!(((_n) == (_sentinel)) || (((_min) <= (_n)) && ((_n) <= (_max))))) { \
+ struct __constraint_info _ci = {0}; \
+ _ci.func = __func__; \
+ _ci.value = _n; \
+ __stdlib.constraint_handler("Undefined behavior: " \
+ "Parameter " #_n " must be representable as a " #_type \
+ " or be equal to " #_sentinel, &_ci, ERANGE); \
+ } \
+ } while (0)
+
+#define SIGNAL_SAFE(__n) do { \
+ if (__n == 0 && __signal.current != 0) { \
+ struct __constraint_info _ci = {0}; \
+ _ci.func = __func__; \
+ _ci.value = __signal.current; \
+ __stdlib.constraint_handler("Undefined behavior: " \
+ "Standard library function called from signal handler", \
+ &_ci, 0); \
+ } \
+} while (0)
+#else
+
+#define ASSERT_REPRESENTABLE(_n, _min, _max, _type, _sentinel)
+#define ASSERT_NOOVERLAP(__x, __y, __s)
+#define ASSERT_NONNULL(x)
+#define ASSERT_NONZERO(n)
+
+#endif
+
+#endif
diff --git a/src/signal/__signal.c b/src/signal/__signal.c
new file mode 100644
index 00000000..1c212bd1
--- /dev/null
+++ b/src/signal/__signal.c
@@ -0,0 +1,3 @@
+#include "_signal.h"
+
+struct __signal __signal = {0};
diff --git a/src/signal/_signal.h b/src/signal/_signal.h
new file mode 100644
index 00000000..d699834c
--- /dev/null
+++ b/src/signal/_signal.h
@@ -0,0 +1,8 @@
+#ifndef SIGNAL__SIGNAL_H
+#define SIGNAL__SIGNAL_H
+
+extern struct __signal {
+ int current;
+} __signal;
+
+#endif