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