xref: /haiku/src/tests/system/libroot/posix/pthread_sigqueue.cpp (revision f758e73fe6df01190d54716802d51635b609e1fd)
1*f758e73fSJérôme Duval /*
2*f758e73fSJérôme Duval  * Copyright 2024, Haiku, Inc. All Rights Reserved.
3*f758e73fSJérôme Duval  * Distributed under the terms of the MIT License.
4*f758e73fSJérôme Duval  *
5*f758e73fSJérôme Duval  * Authors:
6*f758e73fSJérôme Duval  *		Jérôme Duval, jerome.duval@gmail.com
7*f758e73fSJérôme Duval  * Inspired from Android signal_test.cpp
8*f758e73fSJérôme Duval  */
9*f758e73fSJérôme Duval 
10*f758e73fSJérôme Duval 
11*f758e73fSJérôme Duval #include <errno.h>
12*f758e73fSJérôme Duval #include <pthread.h>
13*f758e73fSJérôme Duval #include <signal.h>
14*f758e73fSJérôme Duval #include <stdio.h>
15*f758e73fSJérôme Duval #include <stdlib.h>
16*f758e73fSJérôme Duval #include <sys/cdefs.h>
17*f758e73fSJérôme Duval #include <sys/types.h>
18*f758e73fSJérôme Duval #include <unistd.h>
19*f758e73fSJérôme Duval 
20*f758e73fSJérôme Duval 
21*f758e73fSJérôme Duval #define ASSERT_EQ(x,y) { if (x != y) { fprintf(stderr, "assert failed %s %s\n", #x, #y); exit(1); }}
22*f758e73fSJérôme Duval #define ASSERT_ERRNO(x) ASSERT_EQ(errno, x)
23*f758e73fSJérôme Duval 
24*f758e73fSJérôme Duval 
25*f758e73fSJérôme Duval class ScopedSignalHandler
26*f758e73fSJérôme Duval {
27*f758e73fSJérôme Duval public:
ScopedSignalHandler(int signal,void (* handler)(int,siginfo_t *,void *))28*f758e73fSJérôme Duval 	ScopedSignalHandler(int signal, void (*handler)(int, siginfo_t*, void*))
29*f758e73fSJérôme Duval 		: signalNumber(signal)
30*f758e73fSJérôme Duval 	{
31*f758e73fSJérôme Duval 		sigemptyset(&action.sa_mask);
32*f758e73fSJérôme Duval 		action.sa_flags = SA_SIGINFO;
33*f758e73fSJérôme Duval 		action.sa_sigaction = handler;
34*f758e73fSJérôme Duval 		sigaction(signalNumber, &action, &oldAction);
35*f758e73fSJérôme Duval 	}
~ScopedSignalHandler()36*f758e73fSJérôme Duval 	~ScopedSignalHandler()
37*f758e73fSJérôme Duval 	{
38*f758e73fSJérôme Duval 		sigaction(signalNumber, &oldAction, NULL);
39*f758e73fSJérôme Duval 	}
40*f758e73fSJérôme Duval private:
41*f758e73fSJérôme Duval 	struct sigaction action;
42*f758e73fSJérôme Duval 	struct sigaction oldAction;
43*f758e73fSJérôme Duval 	const int signalNumber;
44*f758e73fSJérôme Duval };
45*f758e73fSJérôme Duval 
46*f758e73fSJérôme Duval static int gSigqueueSignalHandlerCallCount = 0;
47*f758e73fSJérôme Duval 
48*f758e73fSJérôme Duval static void
SigqueueSignalHandler(int signum,siginfo_t * info,void *)49*f758e73fSJérôme Duval SigqueueSignalHandler(int signum, siginfo_t* info, void*)
50*f758e73fSJérôme Duval {
51*f758e73fSJérôme Duval 	ASSERT_EQ(SIGALRM, signum);
52*f758e73fSJérôme Duval 	ASSERT_EQ(SIGALRM, info->si_signo);
53*f758e73fSJérôme Duval 	ASSERT_EQ(SI_QUEUE, info->si_code);
54*f758e73fSJérôme Duval 	ASSERT_EQ(1, info->si_value.sival_int);
55*f758e73fSJérôme Duval 	++gSigqueueSignalHandlerCallCount;
56*f758e73fSJérôme Duval }
57*f758e73fSJérôme Duval 
58*f758e73fSJérôme Duval 
59*f758e73fSJérôme Duval void
signal_sigqueue()60*f758e73fSJérôme Duval signal_sigqueue()
61*f758e73fSJérôme Duval {
62*f758e73fSJérôme Duval 	gSigqueueSignalHandlerCallCount = 0;
63*f758e73fSJérôme Duval 	ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler);
64*f758e73fSJérôme Duval 	sigval sigval = {.sival_int = 1};
65*f758e73fSJérôme Duval 	errno = 0;
66*f758e73fSJérôme Duval 	ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval));
67*f758e73fSJérôme Duval 	ASSERT_ERRNO(0);
68*f758e73fSJérôme Duval 	ASSERT_EQ(1, gSigqueueSignalHandlerCallCount);
69*f758e73fSJérôme Duval }
70*f758e73fSJérôme Duval 
71*f758e73fSJérôme Duval 
72*f758e73fSJérôme Duval void
signal_pthread_sigqueue_self()73*f758e73fSJérôme Duval signal_pthread_sigqueue_self()
74*f758e73fSJérôme Duval {
75*f758e73fSJérôme Duval 	gSigqueueSignalHandlerCallCount = 0;
76*f758e73fSJérôme Duval 	ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler);
77*f758e73fSJérôme Duval 	sigval sigval = {.sival_int = 1};
78*f758e73fSJérôme Duval 	errno = 0;
79*f758e73fSJérôme Duval 	ASSERT_EQ(0, pthread_sigqueue(pthread_self(), SIGALRM, sigval));
80*f758e73fSJérôme Duval 	ASSERT_ERRNO(0);
81*f758e73fSJérôme Duval 	ASSERT_EQ(1, gSigqueueSignalHandlerCallCount);
82*f758e73fSJérôme Duval }
83*f758e73fSJérôme Duval 
84*f758e73fSJérôme Duval 
85*f758e73fSJérôme Duval void
signal_pthread_sigqueue_other()86*f758e73fSJérôme Duval signal_pthread_sigqueue_other()
87*f758e73fSJérôme Duval {
88*f758e73fSJérôme Duval 	gSigqueueSignalHandlerCallCount = 0;
89*f758e73fSJérôme Duval 	ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler);
90*f758e73fSJérôme Duval 	sigval sigval = {.sival_int = 1};
91*f758e73fSJérôme Duval 	sigset_t mask;
92*f758e73fSJérôme Duval 	sigfillset(&mask);
93*f758e73fSJérôme Duval 	pthread_sigmask(SIG_SETMASK, &mask, nullptr);
94*f758e73fSJérôme Duval 	pthread_t thread;
95*f758e73fSJérôme Duval 	int rc = pthread_create(&thread, nullptr,
96*f758e73fSJérôme Duval 		[](void*) -> void* {
97*f758e73fSJérôme Duval 			sigset_t mask;
98*f758e73fSJérôme Duval 			sigemptyset(&mask);
99*f758e73fSJérôme Duval 			sigsuspend(&mask);
100*f758e73fSJérôme Duval 			return nullptr;
101*f758e73fSJérôme Duval 		}, nullptr);
102*f758e73fSJérôme Duval 	ASSERT_EQ(0, rc);
103*f758e73fSJérôme Duval 	errno = 0;
104*f758e73fSJérôme Duval 	ASSERT_EQ(0, pthread_sigqueue(thread, SIGALRM, sigval));
105*f758e73fSJérôme Duval 	ASSERT_ERRNO(0);
106*f758e73fSJérôme Duval 	pthread_join(thread, nullptr);
107*f758e73fSJérôme Duval 	ASSERT_EQ(1, gSigqueueSignalHandlerCallCount);
108*f758e73fSJérôme Duval }
109*f758e73fSJérôme Duval 
110*f758e73fSJérôme Duval 
111*f758e73fSJérôme Duval extern "C" int
main()112*f758e73fSJérôme Duval main()
113*f758e73fSJérôme Duval {
114*f758e73fSJérôme Duval 	printf("signal_sigqueue\n");
115*f758e73fSJérôme Duval 	signal_sigqueue();
116*f758e73fSJérôme Duval 	printf("signal_pthread_sigqueue_self\n");
117*f758e73fSJérôme Duval 	signal_pthread_sigqueue_self();
118*f758e73fSJérôme Duval 	printf("signal_pthread_sigqueue_other\n");
119*f758e73fSJérôme Duval 	signal_pthread_sigqueue_other();
120*f758e73fSJérôme Duval }
121