linux-kselftest.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] signal handling support for nolibc
@ 2025-07-09 15:55 Benjamin Berg
  2025-07-09 15:55 ` [PATCH 1/3] tools/nolibc: show failed run if test process crashes Benjamin Berg
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Benjamin Berg @ 2025-07-09 15:55 UTC (permalink / raw)
  To: Willy Tarreau, Thomas Weißschuh, linux-kselftest; +Cc: Benjamin Berg

From: Benjamin Berg <benjamin.berg@intel.com>

Hi,

This patchset adds signal handling to nolibc. Initially, I would like to
use this for tests. But in the long run, the goal is to use nolibc for
the UML kernel itself. In both cases, signal handling will be needed.

Benjamin

Benjamin Berg (3):
  tools/nolibc: show failed run if test process crashes
  tools/nolibc: add more generic BITSET_* macros for FD_*
  tools/nolibc: add signal support

 tools/include/nolibc/arch-arm.h               |   7 ++
 tools/include/nolibc/arch-arm64.h             |   3 +
 tools/include/nolibc/arch-loongarch.h         |   3 +
 tools/include/nolibc/arch-m68k.h              |  10 ++
 tools/include/nolibc/arch-mips.h              |   3 +
 tools/include/nolibc/arch-powerpc.h           |   8 ++
 tools/include/nolibc/arch-riscv.h             |   3 +
 tools/include/nolibc/arch-s390.h              |   8 +-
 tools/include/nolibc/arch-sh.h                |   5 +
 tools/include/nolibc/arch-sparc.h             |  47 ++++++++
 tools/include/nolibc/arch-x86.h               |  13 +++
 tools/include/nolibc/signal.h                 | 103 ++++++++++++++++++
 tools/include/nolibc/sys.h                    |   2 +-
 tools/include/nolibc/time.h                   |   3 +-
 tools/include/nolibc/types.h                  |  67 ++++++------
 .../testing/selftests/nolibc/Makefile.nolibc  |   3 +-
 tools/testing/selftests/nolibc/nolibc-test.c  |  67 ++++++++++++
 17 files changed, 319 insertions(+), 36 deletions(-)

-- 
2.50.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] tools/nolibc: show failed run if test process crashes
  2025-07-09 15:55 [PATCH 0/3] signal handling support for nolibc Benjamin Berg
@ 2025-07-09 15:55 ` Benjamin Berg
  2025-07-09 16:27   ` Thomas Weißschuh
  2025-07-09 15:55 ` [PATCH 2/3] tools/nolibc: add more generic BITSET_* macros for FD_* Benjamin Berg
  2025-07-09 15:55 ` [PATCH 3/3] tools/nolibc: add signal support Benjamin Berg
  2 siblings, 1 reply; 10+ messages in thread
From: Benjamin Berg @ 2025-07-09 15:55 UTC (permalink / raw)
  To: Willy Tarreau, Thomas Weißschuh, linux-kselftest; +Cc: Benjamin Berg

From: Benjamin Berg <benjamin.berg@intel.com>

The logic would not catch if the test process crashes and would
incorrectly report a "success" state. Fix this by looking for the final
"Total number of errors:" message and printing "failure" if it was not
seen.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
---
 tools/testing/selftests/nolibc/Makefile.nolibc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/nolibc/Makefile.nolibc b/tools/testing/selftests/nolibc/Makefile.nolibc
index 8cb65392fa10..51ba853dd97e 100644
--- a/tools/testing/selftests/nolibc/Makefile.nolibc
+++ b/tools/testing/selftests/nolibc/Makefile.nolibc
@@ -245,8 +245,9 @@ endif
 include $(srctree)/tools/scripts/Makefile.include
 
 REPORT  ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++; print;} /\[SKIPPED\][\r]*$$/{s++} \
+		/^Total number of errors:/{done++} \
 		END{ printf("\n%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \
-		if (f || !p) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \
+		if (f || !p || !done) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \
 		printf("\nSee all results in %s\n", ARGV[1]); }'
 
 help:
-- 
2.50.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] tools/nolibc: add more generic BITSET_* macros for FD_*
  2025-07-09 15:55 [PATCH 0/3] signal handling support for nolibc Benjamin Berg
  2025-07-09 15:55 ` [PATCH 1/3] tools/nolibc: show failed run if test process crashes Benjamin Berg
@ 2025-07-09 15:55 ` Benjamin Berg
  2025-07-09 18:36   ` Thomas Weißschuh
  2025-07-09 15:55 ` [PATCH 3/3] tools/nolibc: add signal support Benjamin Berg
  2 siblings, 1 reply; 10+ messages in thread
From: Benjamin Berg @ 2025-07-09 15:55 UTC (permalink / raw)
  To: Willy Tarreau, Thomas Weißschuh, linux-kselftest; +Cc: Benjamin Berg

From: Benjamin Berg <benjamin.berg@intel.com>

The FD_* macros are assuming a specific type for the bitset. Add new
macros that introspect the type of the passed variable in order to know
the size of the bitset. This way the same macros can be used for other
purposes.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
---
 tools/include/nolibc/types.h | 67 +++++++++++++++++++-----------------
 1 file changed, 36 insertions(+), 31 deletions(-)

diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h
index 16c6e9ec9451..3100771e21ad 100644
--- a/tools/include/nolibc/types.h
+++ b/tools/include/nolibc/types.h
@@ -115,48 +115,53 @@
 #define EXIT_SUCCESS 0
 #define EXIT_FAILURE 1
 
-#define FD_SETIDXMASK (8 * sizeof(unsigned long))
-#define FD_SETBITMASK (8 * sizeof(unsigned long)-1)
-
-/* for select() */
-typedef struct {
-	unsigned long fds[(FD_SETSIZE + FD_SETBITMASK) / FD_SETIDXMASK];
-} fd_set;
-
-#define FD_CLR(fd, set) do {						\
-		fd_set *__set = (set);					\
-		int __fd = (fd);					\
-		if (__fd >= 0)						\
-			__set->fds[__fd / FD_SETIDXMASK] &=		\
-				~(1U << (__fd & FD_SETBITMASK));	\
+#define BITSET_CLR(num, set) do {					  \
+		__typeof__(set) *__set = &(set);			  \
+		int __num = (num);					  \
+		if (__num >= 0 && __num < 8 * (ssize_t)sizeof(*__set))	  \
+			(*__set)[__num / (8 * sizeof(set[0]))] &=	  \
+				~(1U << (__num % (8 * sizeof(**__set)))); \
 	} while (0)
 
-#define FD_SET(fd, set) do {						\
-		fd_set *__set = (set);					\
-		int __fd = (fd);					\
-		if (__fd >= 0)						\
-			__set->fds[__fd / FD_SETIDXMASK] |=		\
-				1 << (__fd & FD_SETBITMASK);		\
+#define BITSET_SET(num, set) do {					\
+		__typeof__(set) *__set = &(set);			\
+		int __num = (num);					\
+		if (__num >= 0 && __num < 8 * (ssize_t)sizeof(*__set))	\
+			(*__set)[__num / (8 * sizeof(set[0]))] |=	\
+				1U << (__num % (8 * sizeof(**__set)));	\
 	} while (0)
 
-#define FD_ISSET(fd, set) ({						\
-			fd_set *__set = (set);				\
-			int __fd = (fd);				\
+#define BITSET_ISSET(num, set) ({					\
+		__typeof__(set) *__set = &(set);			\
+		int __num = (num);					\
 		int __r = 0;						\
-		if (__fd >= 0)						\
-			__r = !!(__set->fds[__fd / FD_SETIDXMASK] &	\
-1U << (__fd & FD_SETBITMASK));						\
-		__r;							\
+		if (__num >= 0 && __num < 8 * (ssize_t)sizeof(*__set))	\
+			__r = (*__set)[__num / (8 * sizeof(set[0]))] &	\
+			      (1U << (__num % (8 * sizeof(**__set))));	\
+		!!__r;							\
 	})
 
-#define FD_ZERO(set) do {						\
-		fd_set *__set = (set);					\
+#define BITSET_ZERO(set) do {						\
+		__typeof__(set) *__set = &(set);			\
 		int __idx;						\
-		int __size = (FD_SETSIZE+FD_SETBITMASK) / FD_SETIDXMASK;\
+		int __size = sizeof(*__set) / sizeof(**__set);		\
 		for (__idx = 0; __idx < __size; __idx++)		\
-			__set->fds[__idx] = 0;				\
+			(*__set)[__idx] = 0;				\
 	} while (0)
 
+#define FD_SETIDXMASK (8 * sizeof(unsigned long))
+#define FD_SETBITMASK (8 * sizeof(unsigned long)-1)
+
+/* for select() */
+typedef struct {
+	unsigned long fds[(FD_SETSIZE + FD_SETBITMASK) / FD_SETIDXMASK];
+} fd_set;
+
+#define FD_CLR(fd, set) BITSET_CLR(fd, (set)->fds)
+#define FD_SET(fd, set) BITSET_SET(fd, (set)->fds)
+#define FD_ISSET(fd, set) BITSET_ISSET(fd, (set)->fds)
+#define FD_ZERO(set) BITSET_ZERO((set)->fds)
+
 /* for getdents64() */
 struct linux_dirent64 {
 	uint64_t       d_ino;
-- 
2.50.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] tools/nolibc: add signal support
  2025-07-09 15:55 [PATCH 0/3] signal handling support for nolibc Benjamin Berg
  2025-07-09 15:55 ` [PATCH 1/3] tools/nolibc: show failed run if test process crashes Benjamin Berg
  2025-07-09 15:55 ` [PATCH 2/3] tools/nolibc: add more generic BITSET_* macros for FD_* Benjamin Berg
@ 2025-07-09 15:55 ` Benjamin Berg
  2025-07-09 21:21   ` Thomas Weißschuh
  2 siblings, 1 reply; 10+ messages in thread
From: Benjamin Berg @ 2025-07-09 15:55 UTC (permalink / raw)
  To: Willy Tarreau, Thomas Weißschuh, linux-kselftest; +Cc: Benjamin Berg

From: Benjamin Berg <benjamin.berg@intel.com>

Add support for sigaction() and implement the normal sa_mask helpers.

On many architectures, linux/signal.h pulls in compatibility definitions
for the old sigaction syscall instead of rt_sigaction. However, the
kernel can be compiled without support for this compatibility syscall
and it also results in sa_mask to be too small for realtime signals.

To work around this, the includes are handled separately for each
architecture. This way either linux/signal.h or the asm-generic headers
can be used to get the correct definition for the rt_sigaction syscall
including sigset_t.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>

---

v1:
- Update architecture support (adding sh)
- Move sparc sys_rt_sigaction logic into its header
- Add sig_atomic_t
- Use new BITSET_* macros
- Move test into syscall suite
- Various other small changes

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
---
 tools/include/nolibc/arch-arm.h              |   7 ++
 tools/include/nolibc/arch-arm64.h            |   3 +
 tools/include/nolibc/arch-loongarch.h        |   3 +
 tools/include/nolibc/arch-m68k.h             |  10 ++
 tools/include/nolibc/arch-mips.h             |   3 +
 tools/include/nolibc/arch-powerpc.h          |   8 ++
 tools/include/nolibc/arch-riscv.h            |   3 +
 tools/include/nolibc/arch-s390.h             |   8 +-
 tools/include/nolibc/arch-sh.h               |   5 +
 tools/include/nolibc/arch-sparc.h            |  47 +++++++++
 tools/include/nolibc/arch-x86.h              |  13 +++
 tools/include/nolibc/signal.h                | 103 +++++++++++++++++++
 tools/include/nolibc/sys.h                   |   2 +-
 tools/include/nolibc/time.h                  |   3 +-
 tools/testing/selftests/nolibc/nolibc-test.c |  67 ++++++++++++
 15 files changed, 281 insertions(+), 4 deletions(-)

diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-arm.h
index 1f66e7e5a444..1faf6c2dbeb8 100644
--- a/tools/include/nolibc/arch-arm.h
+++ b/tools/include/nolibc/arch-arm.h
@@ -10,6 +10,13 @@
 #include "compiler.h"
 #include "crt.h"
 
+/* Needed to get the correct struct sigaction definition */
+#define SA_RESTORER	0x04000000
+
+/* Avoid linux/signal.h, it has an incorrect _NSIG and sigset_t */
+#include <asm-generic/signal.h>
+#include <asm-generic/siginfo.h>
+
 /* Syscalls for ARM in ARM or Thumb modes :
  *   - registers are 32-bit
  *   - stack is 8-byte aligned
diff --git a/tools/include/nolibc/arch-arm64.h b/tools/include/nolibc/arch-arm64.h
index 02a3f74c8ec8..ad14fc0ae5cb 100644
--- a/tools/include/nolibc/arch-arm64.h
+++ b/tools/include/nolibc/arch-arm64.h
@@ -10,6 +10,9 @@
 #include "compiler.h"
 #include "crt.h"
 
+/* Architecture has a usable linux/signal.h */
+#include <linux/signal.h>
+
 /* Syscalls for ARM64 :
  *   - registers are 64-bit
  *   - stack is 16-byte aligned
diff --git a/tools/include/nolibc/arch-loongarch.h b/tools/include/nolibc/arch-loongarch.h
index 5511705303ea..68d60d04ef59 100644
--- a/tools/include/nolibc/arch-loongarch.h
+++ b/tools/include/nolibc/arch-loongarch.h
@@ -10,6 +10,9 @@
 #include "compiler.h"
 #include "crt.h"
 
+/* Architecture has a usable linux/signal.h */
+#include <linux/signal.h>
+
 /* Syscalls for LoongArch :
  *   - stack is 16-byte aligned
  *   - syscall number is passed in a7
diff --git a/tools/include/nolibc/arch-m68k.h b/tools/include/nolibc/arch-m68k.h
index 6dac1845f298..981b4cc55a69 100644
--- a/tools/include/nolibc/arch-m68k.h
+++ b/tools/include/nolibc/arch-m68k.h
@@ -13,6 +13,16 @@
 #include "compiler.h"
 #include "crt.h"
 
+/*
+ * Needed to get the correct struct sigaction definition. m68k does not use
+ * sa_restorer, but it is included in the structure.
+ */
+#define SA_RESTORER	0x04000000
+
+/* Avoid linux/signal.h, it has an incorrect _NSIG and sigset_t */
+#include <asm-generic/signal.h>
+#include <asm-generic/siginfo.h>
+
 #define _NOLIBC_SYSCALL_CLOBBERLIST "memory"
 
 #define my_syscall0(num)                                                      \
diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
index 0cbac63b249a..fb2f503f151f 100644
--- a/tools/include/nolibc/arch-mips.h
+++ b/tools/include/nolibc/arch-mips.h
@@ -14,6 +14,9 @@
 #error Unsupported MIPS ABI
 #endif
 
+/* Architecture has a usable linux/signal.h */
+#include <linux/signal.h>
+
 /* Syscalls for MIPS ABI O32 :
  *   - WARNING! there's always a delayed slot!
  *   - WARNING again, the syntax is different, registers take a '$' and numbers
diff --git a/tools/include/nolibc/arch-powerpc.h b/tools/include/nolibc/arch-powerpc.h
index 204564bbcd32..c846a7ddcf3c 100644
--- a/tools/include/nolibc/arch-powerpc.h
+++ b/tools/include/nolibc/arch-powerpc.h
@@ -10,6 +10,14 @@
 #include "compiler.h"
 #include "crt.h"
 
+/* Needed to get the correct struct sigaction definition */
+#define SA_RESTORER	0x04000000
+#define _NOLIBC_ARCH_NEEDS_SA_RESTORER
+
+/* Avoid linux/signal.h, it has an incorrect _NSIG and sigset_t */
+#include <asm-generic/signal.h>
+#include <asm-generic/siginfo.h>
+
 /* Syscalls for PowerPC :
  *   - stack is 16-byte aligned
  *   - syscall number is passed in r0
diff --git a/tools/include/nolibc/arch-riscv.h b/tools/include/nolibc/arch-riscv.h
index 885383a86c38..709e6a262d9a 100644
--- a/tools/include/nolibc/arch-riscv.h
+++ b/tools/include/nolibc/arch-riscv.h
@@ -10,6 +10,9 @@
 #include "compiler.h"
 #include "crt.h"
 
+/* Architecture has a usable linux/signal.h */
+#include <linux/signal.h>
+
 /* Syscalls for RISCV :
  *   - stack is 16-byte aligned
  *   - syscall number is passed in a7
diff --git a/tools/include/nolibc/arch-s390.h b/tools/include/nolibc/arch-s390.h
index df4c3cc713ac..0dccb6d1ad64 100644
--- a/tools/include/nolibc/arch-s390.h
+++ b/tools/include/nolibc/arch-s390.h
@@ -5,13 +5,19 @@
 
 #ifndef _NOLIBC_ARCH_S390_H
 #define _NOLIBC_ARCH_S390_H
-#include <linux/signal.h>
 #include <linux/unistd.h>
 
 #include "compiler.h"
 #include "crt.h"
 #include "std.h"
 
+/* Needed to get the correct struct sigaction definition */
+#define SA_RESTORER	0x04000000
+
+/* Avoid linux/signal.h, it has an incorrect _NSIG and sigset_t */
+#include <asm-generic/signal.h>
+#include <asm-generic/siginfo.h>
+
 /* Syscalls for s390:
  *   - registers are 64-bit
  *   - syscall number is passed in r1
diff --git a/tools/include/nolibc/arch-sh.h b/tools/include/nolibc/arch-sh.h
index a96b8914607e..3378afc78e26 100644
--- a/tools/include/nolibc/arch-sh.h
+++ b/tools/include/nolibc/arch-sh.h
@@ -7,9 +7,14 @@
 #ifndef _NOLIBC_ARCH_SH_H
 #define _NOLIBC_ARCH_SH_H
 
+#include <linux/unistd.h>
+
 #include "compiler.h"
 #include "crt.h"
 
+/* Architecture has a usable linux/signal.h */
+#include <linux/signal.h>
+
 /*
  * Syscalls for SuperH:
  *   - registers are 32bit wide
diff --git a/tools/include/nolibc/arch-sparc.h b/tools/include/nolibc/arch-sparc.h
index ca420d843e25..c9574e7f795a 100644
--- a/tools/include/nolibc/arch-sparc.h
+++ b/tools/include/nolibc/arch-sparc.h
@@ -12,6 +12,10 @@
 #include "compiler.h"
 #include "crt.h"
 
+/* The includes are sane, if one sets __WANT_POSIX1B_SIGNALS__ */
+#define __WANT_POSIX1B_SIGNALS__
+#include <linux/signal.h>
+
 /*
  * Syscalls for SPARC:
  *   - registers are native word size
@@ -204,4 +208,47 @@ pid_t sys_vfork(void)
 }
 #define sys_vfork sys_vfork
 
+#define __nolibc_sa_restorer __nolibc_sa_restorer
+void __nolibc_sa_restorer(void);
+void __nolibc_sa_restorer_wrapper(void);
+void __attribute__((weak,noreturn)) __nolibc_entrypoint __no_stack_protector
+__nolibc_sa_restorer_wrapper(void)
+{
+	/* The C function will have a prologue corrupting "sp" */
+	__asm__  volatile (
+		".section .text\n"
+		".align 4\n"
+		".type __nolibc_sa_restorer, @function\n"
+		"__nolibc_sa_restorer:\n"
+		"nop\n"
+		"nop\n"
+		"mov %0, %%g1 \n"
+#ifdef __arch64__
+		"t 0x6d\n"
+#else
+		"t 0x10\n"
+#endif
+		".size __nolibc_sa_restorer, .-__nolibc_sa_restorer\n"
+		:: "n"(__NR_rt_sigreturn)
+	);
+	__nolibc_entrypoint_epilogue();
+}
+
+/*
+ * sparc has ODD_RT_SIGACTION, we need to pass the restorer as an argument
+ * to rt_sigaction.
+ */
+#define sys_rt_sigaction sys_rt_sigaction
+static __attribute__((unused))
+int sys_rt_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
+{
+	struct sigaction real_act = *act;
+
+	/* Otherwise we would need to use sigreturn instead of rt_sigreturn */
+	real_act.sa_flags |= SA_SIGINFO;
+
+	return my_syscall5(__NR_rt_sigaction, signum, &real_act, oldact,
+			   __nolibc_sa_restorer, sizeof(act->sa_mask));
+}
+
 #endif /* _NOLIBC_ARCH_SPARC_H */
diff --git a/tools/include/nolibc/arch-x86.h b/tools/include/nolibc/arch-x86.h
index d3efc0c3b8ad..1fe75203d834 100644
--- a/tools/include/nolibc/arch-x86.h
+++ b/tools/include/nolibc/arch-x86.h
@@ -10,8 +10,21 @@
 #include "compiler.h"
 #include "crt.h"
 
+/* Needed to get the correct struct sigaction definition */
+#define SA_RESTORER	0x04000000
+
+/* Restorer must be set on x86 for both 32 and 64 bit */
+#define _NOLIBC_ARCH_NEEDS_SA_RESTORER
+
+/* Avoid linux/signal.h, it has an incorrect _NSIG and sigset_t */
+#include <asm-generic/signal.h>
+#include <asm-generic/siginfo.h>
+
 #if !defined(__x86_64__)
 
+/* On i386 we need to set SA_SIGINFO to use rt_sigreturn */
+#define _NOLIBC_ARCH_FORCE_SIG_FLAGS SA_SIGINFO
+
 /* Syscalls for i386 :
  *   - mostly similar to x86_64
  *   - registers are 32-bit
diff --git a/tools/include/nolibc/signal.h b/tools/include/nolibc/signal.h
index ac13e53ac31d..cbba57012767 100644
--- a/tools/include/nolibc/signal.h
+++ b/tools/include/nolibc/signal.h
@@ -14,6 +14,14 @@
 #include "arch.h"
 #include "types.h"
 #include "sys.h"
+#include "string.h"
+/* other signal definitions are included by arch.h */
+
+/* The kernel headers do not provide a sig_atomic_t definition */
+#ifndef __sig_atomic_t_defined
+#define __sig_atomic_t_defined 1
+typedef int sig_atomic_t;
+#endif
 
 /* This one is not marked static as it's needed by libgcc for divide by zero */
 int raise(int signal);
@@ -23,4 +31,99 @@ int raise(int signal)
 	return sys_kill(sys_getpid(), signal);
 }
 
+/*
+ * sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
+ */
+#if defined(_NOLIBC_ARCH_NEEDS_SA_RESTORER) && !defined(__nolibc_sa_restorer)
+static __no_stack_protector
+void __nolibc_sa_restorer(void)
+{
+	my_syscall0(__NR_rt_sigreturn);
+}
+#endif
+
+#ifndef sys_rt_sigaction
+static __attribute__((unused))
+int sys_rt_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
+{
+	struct sigaction real_act = *act;
+#if defined(_NOLIBC_ARCH_NEEDS_SA_RESTORER)
+	if (!(real_act.sa_flags & SA_RESTORER)) {
+		real_act.sa_flags |= SA_RESTORER;
+		real_act.sa_restorer = __nolibc_sa_restorer;
+	}
+#endif
+#ifdef _NOLIBC_ARCH_FORCE_SIG_FLAGS
+	real_act.sa_flags |= _NOLIBC_ARCH_FORCE_SIG_FLAGS;
+#endif
+
+	return my_syscall4(__NR_rt_sigaction, signum, &real_act, oldact,
+			   sizeof(act->sa_mask));
+}
+#endif
+
+static __attribute__((unused))
+int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
+{
+	return __sysret(sys_rt_sigaction(signum, act, oldact));
+}
+
+/*
+ * int sigemptyset(sigset_t *set)
+ */
+static __attribute__((unused))
+int sigemptyset(sigset_t *set)
+{
+	BITSET_ZERO(set->sig);
+	return 0;
+}
+
+/*
+ * int sigfillset(sigset_t *set)
+ */
+static __attribute__((unused))
+int sigfillset(sigset_t *set)
+{
+	memset(set, 0xff, sizeof(*set));
+	return 0;
+}
+
+/*
+ * int sigaddset(sigset_t *set, int signum)
+ */
+static __attribute__((unused))
+int sigaddset(sigset_t *set, int signum)
+{
+	if (signum < 1 || signum > _NSIG)
+		return __sysret(-EINVAL);
+
+	BITSET_SET(signum - 1, set->sig);
+	return 0;
+}
+
+/*
+ * int sigdelset(sigset_t *set, int signum)
+ */
+static __attribute__((unused))
+int sigdelset(sigset_t *set, int signum)
+{
+	if (signum < 1 || signum > _NSIG)
+		return __sysret(-EINVAL);
+
+	BITSET_CLR(signum - 1, set->sig);
+	return 0;
+}
+
+/*
+ * int sigismember(sigset_t *set, int signum)
+ */
+static __attribute__((unused))
+int sigismember(sigset_t *set, int signum)
+{
+	if (signum < 1 || signum > _NSIG)
+		return __sysret(-EINVAL);
+
+	return BITSET_ISSET(signum - 1, set->sig);
+}
+
 #endif /* _NOLIBC_SIGNAL_H */
diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h
index 295e71d34aba..73b935576561 100644
--- a/tools/include/nolibc/sys.h
+++ b/tools/include/nolibc/sys.h
@@ -14,7 +14,6 @@
 
 /* system includes */
 #include <linux/unistd.h>
-#include <linux/signal.h>  /* for SIGCHLD */
 #include <linux/termios.h>
 #include <linux/mman.h>
 #include <linux/fs.h>
@@ -24,6 +23,7 @@
 #include <linux/fcntl.h> /* for O_* and AT_* */
 #include <linux/sched.h> /* for clone_args */
 #include <linux/stat.h>  /* for statx() */
+/* signal definitions are included by arch.h */
 
 #include "errno.h"
 #include "stdarg.h"
diff --git a/tools/include/nolibc/time.h b/tools/include/nolibc/time.h
index d02bc44d2643..103574f76515 100644
--- a/tools/include/nolibc/time.h
+++ b/tools/include/nolibc/time.h
@@ -14,9 +14,8 @@
 #include "arch.h"
 #include "types.h"
 #include "sys.h"
-
-#include <linux/signal.h>
 #include <linux/time.h>
+/* signal definitions are included by arch.h */
 
 static __inline__
 void __nolibc_timespec_user_to_kernel(const struct timespec *ts, struct __kernel_timespec *kts)
diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
index a297ee0d6d07..0bed3270a867 100644
--- a/tools/testing/selftests/nolibc/nolibc-test.c
+++ b/tools/testing/selftests/nolibc/nolibc-test.c
@@ -1270,6 +1270,72 @@ int test_namespace(void)
 	return ret;
 }
 
+sig_atomic_t signal_check;
+
+static void sighandler(int signum)
+{
+	if (signum == SIGUSR1) {
+		kill(getpid(), SIGUSR2);
+		signal_check = 1;
+	} else {
+		signal_check++;
+	}
+}
+
+int test_signals(int test_idx)
+{
+	struct sigaction sa = {
+		.sa_flags = 0,
+		.sa_handler = sighandler,
+	};
+	struct sigaction sa_old = {
+		/* Anything other than SIG_DFL */
+		.sa_handler = sighandler,
+	};
+	int llen; /* line length */
+	int ret = 0;
+	int res;
+
+	signal_check = 0;
+
+	sigemptyset(&sa.sa_mask);
+	sigaddset(&sa.sa_mask, SIGUSR2);
+
+	res = sigaction(SIGUSR1, &sa, &sa_old);
+	llen = printf("    register SIGUSR1: %d", res);
+	EXPECT_SYSZR(1, res);
+	if (res)
+		goto out;
+
+	llen = printf("    sa_old.sa_handler: SIG_DFL (%p)", SIG_DFL);
+	EXPECT_PTREQ(1, SIG_DFL, sa_old.sa_handler);
+	if (res)
+		goto out;
+
+	res = sigaction(SIGUSR2, &sa, NULL);
+	llen = printf("    register SIGUSR2: %d", res);
+	EXPECT_SYSZR(1, res);
+	if (res)
+		goto out;
+
+	/* Trigger the first signal. */
+	kill(getpid(), SIGUSR1);
+
+	/* If signal_check is 1 or higher, then signal emission worked */
+	llen = printf("    signal emission: 1 <= signal_check");
+	EXPECT_GE(1, signal_check, 1);
+
+	/* If it is 2, then signal masking worked */
+	llen = printf("    signal masking: 2 == signal_check");
+	EXPECT_EQ(1, signal_check, 2);
+
+out:
+	llen = printf("%d %s", test_idx, "sigaction");
+	EXPECT_EQ(1, res, 0);
+
+	return ret;
+}
+
 /* Run syscall tests between IDs <min> and <max>.
  * Return 0 on success, non-zero on failure.
  */
@@ -1398,6 +1464,7 @@ int run_syscall(int min, int max)
 		CASE_TEST(syscall_noargs);    EXPECT_SYSEQ(1, syscall(__NR_getpid), getpid()); break;
 		CASE_TEST(syscall_args);      EXPECT_SYSER(1, syscall(__NR_statx, 0, NULL, 0, 0, NULL), -1, EFAULT); break;
 		CASE_TEST(namespace);         EXPECT_SYSZR(euid0 && proc, test_namespace()); break;
+		case __LINE__:                ret += test_signals(test); break;
 		case __LINE__:
 			return ret; /* must be last */
 		/* note: do not set any defaults so as to permit holes above */
-- 
2.50.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] tools/nolibc: show failed run if test process crashes
  2025-07-09 15:55 ` [PATCH 1/3] tools/nolibc: show failed run if test process crashes Benjamin Berg
@ 2025-07-09 16:27   ` Thomas Weißschuh
  0 siblings, 0 replies; 10+ messages in thread
From: Thomas Weißschuh @ 2025-07-09 16:27 UTC (permalink / raw)
  To: Benjamin Berg; +Cc: Willy Tarreau, linux-kselftest, Benjamin Berg

On 2025-07-09 17:55:10+0200, Benjamin Berg wrote:
> From: Benjamin Berg <benjamin.berg@intel.com>
> 
> The logic would not catch if the test process crashes and would
> incorrectly report a "success" state. Fix this by looking for the final
> "Total number of errors:" message and printing "failure" if it was not
> seen.

Nice, I'll pick this up directly.

> Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
> ---
>  tools/testing/selftests/nolibc/Makefile.nolibc | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/nolibc/Makefile.nolibc b/tools/testing/selftests/nolibc/Makefile.nolibc
> index 8cb65392fa10..51ba853dd97e 100644
> --- a/tools/testing/selftests/nolibc/Makefile.nolibc
> +++ b/tools/testing/selftests/nolibc/Makefile.nolibc
> @@ -245,8 +245,9 @@ endif
>  include $(srctree)/tools/scripts/Makefile.include
>  
>  REPORT  ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++; print;} /\[SKIPPED\][\r]*$$/{s++} \
> +		/^Total number of errors:/{done++} \
>  		END{ printf("\n%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \
> -		if (f || !p) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \
> +		if (f || !p || !done) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \
>  		printf("\nSee all results in %s\n", ARGV[1]); }'
>  
>  help:
> -- 
> 2.50.0
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] tools/nolibc: add more generic BITSET_* macros for FD_*
  2025-07-09 15:55 ` [PATCH 2/3] tools/nolibc: add more generic BITSET_* macros for FD_* Benjamin Berg
@ 2025-07-09 18:36   ` Thomas Weißschuh
  2025-07-09 18:44     ` Willy Tarreau
  0 siblings, 1 reply; 10+ messages in thread
From: Thomas Weißschuh @ 2025-07-09 18:36 UTC (permalink / raw)
  To: Benjamin Berg; +Cc: Willy Tarreau, linux-kselftest, Benjamin Berg

On 2025-07-09 17:55:11+0200, Benjamin Berg wrote:
> From: Benjamin Berg <benjamin.berg@intel.com>
> 
> The FD_* macros are assuming a specific type for the bitset. Add new
> macros that introspect the type of the passed variable in order to know
> the size of the bitset. This way the same macros can be used for other
> purposes.
> 
> Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
> ---
>  tools/include/nolibc/types.h | 67 +++++++++++++++++++-----------------
>  1 file changed, 36 insertions(+), 31 deletions(-)
> 
> diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h
> index 16c6e9ec9451..3100771e21ad 100644
> --- a/tools/include/nolibc/types.h
> +++ b/tools/include/nolibc/types.h
> @@ -115,48 +115,53 @@
>  #define EXIT_SUCCESS 0
>  #define EXIT_FAILURE 1
>  
> -#define FD_SETIDXMASK (8 * sizeof(unsigned long))
> -#define FD_SETBITMASK (8 * sizeof(unsigned long)-1)
> -
> -/* for select() */
> -typedef struct {
> -	unsigned long fds[(FD_SETSIZE + FD_SETBITMASK) / FD_SETIDXMASK];
> -} fd_set;
> -
> -#define FD_CLR(fd, set) do {						\
> -		fd_set *__set = (set);					\
> -		int __fd = (fd);					\
> -		if (__fd >= 0)						\
> -			__set->fds[__fd / FD_SETIDXMASK] &=		\
> -				~(1U << (__fd & FD_SETBITMASK));	\
> +#define BITSET_CLR(num, set) do {					  \

__NOLIBC_BITMASK_CLEAR()

To avoid conflicts with user code, being clear about the intent and
having some constency with the kernel code.

> +		__typeof__(set) *__set = &(set);			  \
> +		int __num = (num);					  \
> +		if (__num >= 0 && __num < 8 * (ssize_t)sizeof(*__set))	  \
> +			(*__set)[__num / (8 * sizeof(set[0]))] &=	  \
> +				~(1U << (__num % (8 * sizeof(**__set)))); \
>  	} while (0)
>  
> -#define FD_SET(fd, set) do {						\
> -		fd_set *__set = (set);					\
> -		int __fd = (fd);					\
> -		if (__fd >= 0)						\
> -			__set->fds[__fd / FD_SETIDXMASK] |=		\
> -				1 << (__fd & FD_SETBITMASK);		\
> +#define BITSET_SET(num, set) do {					\
> +		__typeof__(set) *__set = &(set);			\
> +		int __num = (num);					\
> +		if (__num >= 0 && __num < 8 * (ssize_t)sizeof(*__set))	\
> +			(*__set)[__num / (8 * sizeof(set[0]))] |=	\
> +				1U << (__num % (8 * sizeof(**__set)));	\
>  	} while (0)
>  
> -#define FD_ISSET(fd, set) ({						\
> -			fd_set *__set = (set);				\
> -			int __fd = (fd);				\
> +#define BITSET_ISSET(num, set) ({					\

__NOLIBC_BITMASK_TEST()

> +		__typeof__(set) *__set = &(set);			\
> +		int __num = (num);					\
>  		int __r = 0;						\
> -		if (__fd >= 0)						\
> -			__r = !!(__set->fds[__fd / FD_SETIDXMASK] &	\
> -1U << (__fd & FD_SETBITMASK));						\
> -		__r;							\
> +		if (__num >= 0 && __num < 8 * (ssize_t)sizeof(*__set))	\
> +			__r = (*__set)[__num / (8 * sizeof(set[0]))] &	\
> +			      (1U << (__num % (8 * sizeof(**__set))));	\
> +		!!__r;							\
>  	})
>  
> -#define FD_ZERO(set) do {						\
> -		fd_set *__set = (set);					\
> +#define BITSET_ZERO(set) do {						\
> +		__typeof__(set) *__set = &(set);			\
>  		int __idx;						\
> -		int __size = (FD_SETSIZE+FD_SETBITMASK) / FD_SETIDXMASK;\
> +		int __size = sizeof(*__set) / sizeof(**__set);		\
>  		for (__idx = 0; __idx < __size; __idx++)		\
> -			__set->fds[__idx] = 0;				\
> +			(*__set)[__idx] = 0;				\
>  	} while (0)
>  
> +#define FD_SETIDXMASK (8 * sizeof(unsigned long))
> +#define FD_SETBITMASK (8 * sizeof(unsigned long)-1)
> +
> +/* for select() */
> +typedef struct {
> +	unsigned long fds[(FD_SETSIZE + FD_SETBITMASK) / FD_SETIDXMASK];
> +} fd_set;
> +
> +#define FD_CLR(fd, set) BITSET_CLR(fd, (set)->fds)
> +#define FD_SET(fd, set) BITSET_SET(fd, (set)->fds)
> +#define FD_ISSET(fd, set) BITSET_ISSET(fd, (set)->fds)
> +#define FD_ZERO(set) BITSET_ZERO((set)->fds)

These could be inline function I think.

> +
>  /* for getdents64() */
>  struct linux_dirent64 {
>  	uint64_t       d_ino;
> -- 
> 2.50.0
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] tools/nolibc: add more generic BITSET_* macros for FD_*
  2025-07-09 18:36   ` Thomas Weißschuh
@ 2025-07-09 18:44     ` Willy Tarreau
  2025-07-11  4:53       ` Thomas Weißschuh
  0 siblings, 1 reply; 10+ messages in thread
From: Willy Tarreau @ 2025-07-09 18:44 UTC (permalink / raw)
  To: Thomas Weißschuh; +Cc: Benjamin Berg, linux-kselftest, Benjamin Berg

Hi Thomas,

On Wed, Jul 09, 2025 at 08:36:49PM +0200, Thomas Weißschuh wrote:
> > +#define FD_CLR(fd, set) BITSET_CLR(fd, (set)->fds)
> > +#define FD_SET(fd, set) BITSET_SET(fd, (set)->fds)
> > +#define FD_ISSET(fd, set) BITSET_ISSET(fd, (set)->fds)
> > +#define FD_ZERO(set) BITSET_ZERO((set)->fds)
> 
> These could be inline function I think.

It's better not do, because man says they are macros, and I've seen
programs using ifdef on them (not to mean that it's common but it's
supposed to be possible according to the man).

Cheers,
Willy

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] tools/nolibc: add signal support
  2025-07-09 15:55 ` [PATCH 3/3] tools/nolibc: add signal support Benjamin Berg
@ 2025-07-09 21:21   ` Thomas Weißschuh
  2025-07-10  5:34     ` Benjamin Berg
  0 siblings, 1 reply; 10+ messages in thread
From: Thomas Weißschuh @ 2025-07-09 21:21 UTC (permalink / raw)
  To: Benjamin Berg; +Cc: Willy Tarreau, linux-kselftest, Benjamin Berg

On 2025-07-09 17:55:12+0200, Benjamin Berg wrote:
(...)

> --- a/tools/testing/selftests/nolibc/nolibc-test.c
> +++ b/tools/testing/selftests/nolibc/nolibc-test.c
> @@ -1270,6 +1270,72 @@ int test_namespace(void)
>  	return ret;
>  }
>  
> +sig_atomic_t signal_check;

static?

> +
> +static void sighandler(int signum)
> +{
> +	if (signum == SIGUSR1) {
> +		kill(getpid(), SIGUSR2);
> +		signal_check = 1;
> +	} else {
> +		signal_check++;
> +	}

This could use some operations which make it clearer which steps
occurred in which order. See the constructor tests.

> +}
> +
> +int test_signals(int test_idx)
> +{
> +	struct sigaction sa = {
> +		.sa_flags = 0,
> +		.sa_handler = sighandler,
> +	};
> +	struct sigaction sa_old = {
> +		/* Anything other than SIG_DFL */
> +		.sa_handler = sighandler,
> +	};
> +	int llen; /* line length */
> +	int ret = 0;
> +	int res;
> +
> +	signal_check = 0;
> +
> +	sigemptyset(&sa.sa_mask);
> +	sigaddset(&sa.sa_mask, SIGUSR2);

I'd like to see some tests for the sigset functions.

> +
> +	res = sigaction(SIGUSR1, &sa, &sa_old);
> +	llen = printf("    register SIGUSR1: %d", res);
> +	EXPECT_SYSZR(1, res);
> +	if (res)
> +		goto out;
> +
> +	llen = printf("    sa_old.sa_handler: SIG_DFL (%p)", SIG_DFL);
> +	EXPECT_PTREQ(1, SIG_DFL, sa_old.sa_handler);
> +	if (res)
> +		goto out;
> +
> +	res = sigaction(SIGUSR2, &sa, NULL);
> +	llen = printf("    register SIGUSR2: %d", res);
> +	EXPECT_SYSZR(1, res);
> +	if (res)
> +		goto out;
> +
> +	/* Trigger the first signal. */
> +	kill(getpid(), SIGUSR1);
> +
> +	/* If signal_check is 1 or higher, then signal emission worked */
> +	llen = printf("    signal emission: 1 <= signal_check");
> +	EXPECT_GE(1, signal_check, 1);
> +
> +	/* If it is 2, then signal masking worked */
> +	llen = printf("    signal masking: 2 == signal_check");
> +	EXPECT_EQ(1, signal_check, 2);
> +
> +out:
> +	llen = printf("%d %s", test_idx, "sigaction");
> +	EXPECT_EQ(1, res, 0);

Restore the default handler afterwards?

> +
> +	return ret;
> +}
> +
>  /* Run syscall tests between IDs <min> and <max>.
>   * Return 0 on success, non-zero on failure.
>   */
> @@ -1398,6 +1464,7 @@ int run_syscall(int min, int max)
>  		CASE_TEST(syscall_noargs);    EXPECT_SYSEQ(1, syscall(__NR_getpid), getpid()); break;
>  		CASE_TEST(syscall_args);      EXPECT_SYSER(1, syscall(__NR_statx, 0, NULL, 0, 0, NULL), -1, EFAULT); break;
>  		CASE_TEST(namespace);         EXPECT_SYSZR(euid0 && proc, test_namespace()); break;
> +		case __LINE__:                ret += test_signals(test); break;
>  		case __LINE__:
>  			return ret; /* must be last */
>  		/* note: do not set any defaults so as to permit holes above */
> -- 
> 2.50.0
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] tools/nolibc: add signal support
  2025-07-09 21:21   ` Thomas Weißschuh
@ 2025-07-10  5:34     ` Benjamin Berg
  0 siblings, 0 replies; 10+ messages in thread
From: Benjamin Berg @ 2025-07-10  5:34 UTC (permalink / raw)
  To: Thomas Weißschuh; +Cc: Willy Tarreau, linux-kselftest

On Wed, 2025-07-09 at 23:21 +0200, Thomas Weißschuh wrote:
> On 2025-07-09 17:55:12+0200, Benjamin Berg wrote:
> (...)
> 
> > --- a/tools/testing/selftests/nolibc/nolibc-test.c
> > +++ b/tools/testing/selftests/nolibc/nolibc-test.c
> > @@ -1270,6 +1270,72 @@ int test_namespace(void)
> >  	return ret;
> >  }
> >  
> > +sig_atomic_t signal_check;
> 
> static?

Oops.

> 
> > +
> > +static void sighandler(int signum)
> > +{
> > +	if (signum == SIGUSR1) {
> > +		kill(getpid(), SIGUSR2);
> > +		signal_check = 1;
> > +	} else {
> > +		signal_check++;
> > +	}
> 
> This could use some operations which make it clearer which steps
> occurred in which order. See the constructor tests.

Could it be that the constructor test logic is buggy? It seems to
simply OR the bottom two bits, but doing that will not verify the
order.

Maybe something more generic like the below macro? i.e. use the bottom
bit to store whether the order has been correct.

/* Set BIT(step + 1), BIT(0) shows whether all steps ran in order */
#define mark_step_done(v, step) do {  \
        v |= v & (1 << ((step) + 1)); \
        if (v == 0 && (step) == 0)    \
            v |= 0x1;                 \
        else if (!(v & (1 << (step))) \
            v &= ~0x1;                \
    } while (0)

> > +}
> > +
> > +int test_signals(int test_idx)
> > +{
> > +	struct sigaction sa = {
> > +		.sa_flags = 0,
> > +		.sa_handler = sighandler,
> > +	};
> > +	struct sigaction sa_old = {
> > +		/* Anything other than SIG_DFL */
> > +		.sa_handler = sighandler,
> > +	};
> > +	int llen; /* line length */
> > +	int ret = 0;
> > +	int res;
> > +
> > +	signal_check = 0;
> > +
> > +	sigemptyset(&sa.sa_mask);
> > +	sigaddset(&sa.sa_mask, SIGUSR2);
> 
> I'd like to see some tests for the sigset functions.

Heh, yeah. sigaddset is kind of tested indirectly when verifying the
emission order. But that just makes it unclear where the test failed.

Benjamin

> > +
> > +	res = sigaction(SIGUSR1, &sa, &sa_old);
> > +	llen = printf("    register SIGUSR1: %d", res);
> > +	EXPECT_SYSZR(1, res);
> > +	if (res)
> > +		goto out;
> > +
> > +	llen = printf("    sa_old.sa_handler: SIG_DFL (%p)",
> > SIG_DFL);
> > +	EXPECT_PTREQ(1, SIG_DFL, sa_old.sa_handler);
> > +	if (res)
> > +		goto out;
> > +
> > +	res = sigaction(SIGUSR2, &sa, NULL);
> > +	llen = printf("    register SIGUSR2: %d", res);
> > +	EXPECT_SYSZR(1, res);
> > +	if (res)
> > +		goto out;
> > +
> > +	/* Trigger the first signal. */
> > +	kill(getpid(), SIGUSR1);
> > +
> > +	/* If signal_check is 1 or higher, then signal emission
> > worked */
> > +	llen = printf("    signal emission: 1 <= signal_check");
> > +	EXPECT_GE(1, signal_check, 1);
> > +
> > +	/* If it is 2, then signal masking worked */
> > +	llen = printf("    signal masking: 2 == signal_check");
> > +	EXPECT_EQ(1, signal_check, 2);
> > +
> > +out:
> > +	llen = printf("%d %s", test_idx, "sigaction");
> > +	EXPECT_EQ(1, res, 0);
> 
> Restore the default handler afterwards?
> 
> > +
> > +	return ret;
> > +}
> > +
> >  /* Run syscall tests between IDs <min> and <max>.
> >   * Return 0 on success, non-zero on failure.
> >   */
> > @@ -1398,6 +1464,7 @@ int run_syscall(int min, int max)
> >  		CASE_TEST(syscall_noargs);    EXPECT_SYSEQ(1,
> > syscall(__NR_getpid), getpid()); break;
> >  		CASE_TEST(syscall_args);      EXPECT_SYSER(1,
> > syscall(__NR_statx, 0, NULL, 0, 0, NULL), -1, EFAULT); break;
> >  		CASE_TEST(namespace);         EXPECT_SYSZR(euid0
> > && proc, test_namespace()); break;
> > +		case __LINE__:                ret +=
> > test_signals(test); break;
> >  		case __LINE__:
> >  			return ret; /* must be last */
> >  		/* note: do not set any defaults so as to permit
> > holes above */
> > -- 
> > 2.50.0
> > 
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] tools/nolibc: add more generic BITSET_* macros for FD_*
  2025-07-09 18:44     ` Willy Tarreau
@ 2025-07-11  4:53       ` Thomas Weißschuh
  0 siblings, 0 replies; 10+ messages in thread
From: Thomas Weißschuh @ 2025-07-11  4:53 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Benjamin Berg, linux-kselftest, Benjamin Berg

On 2025-07-09 20:44:43+0200, Willy Tarreau wrote:
> Hi Thomas,
> 
> On Wed, Jul 09, 2025 at 08:36:49PM +0200, Thomas Weißschuh wrote:
> > > +#define FD_CLR(fd, set) BITSET_CLR(fd, (set)->fds)
> > > +#define FD_SET(fd, set) BITSET_SET(fd, (set)->fds)
> > > +#define FD_ISSET(fd, set) BITSET_ISSET(fd, (set)->fds)
> > > +#define FD_ZERO(set) BITSET_ZERO((set)->fds)
> > 
> > These could be inline function I think.
> 
> It's better not do, because man says they are macros, and I've seen
> programs using ifdef on them (not to mean that it's common but it's
> supposed to be possible according to the man).

Ack. OTOH, we could define a noop-macro for the functions:

static __inline__ void FD_SET(...)
{
}
#define FD_SET FD_SET

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2025-07-11  4:53 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-09 15:55 [PATCH 0/3] signal handling support for nolibc Benjamin Berg
2025-07-09 15:55 ` [PATCH 1/3] tools/nolibc: show failed run if test process crashes Benjamin Berg
2025-07-09 16:27   ` Thomas Weißschuh
2025-07-09 15:55 ` [PATCH 2/3] tools/nolibc: add more generic BITSET_* macros for FD_* Benjamin Berg
2025-07-09 18:36   ` Thomas Weißschuh
2025-07-09 18:44     ` Willy Tarreau
2025-07-11  4:53       ` Thomas Weißschuh
2025-07-09 15:55 ` [PATCH 3/3] tools/nolibc: add signal support Benjamin Berg
2025-07-09 21:21   ` Thomas Weißschuh
2025-07-10  5:34     ` Benjamin Berg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).