1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2018 Google, Inc. 4 * 5 * tgkill() should fail with EAGAIN when RLIMIT_SIGPENDING is reached with a 6 * real-time signal. Test this by starting a child thread with SIGRTMIN 7 * blocked and a limit of 0 pending signals, then attempting to deliver 8 * SIGRTMIN from the parent thread. 9 */ 10 11 #include <pthread.h> 12 #include <signal.h> 13 14 #include "tst_safe_pthread.h" 15 #include "tst_test.h" 16 #include "tgkill.h" 17 18 static void *thread_func(void *arg) 19 { 20 const struct rlimit sigpending = { 21 .rlim_cur = 0, 22 .rlim_max = 0, 23 }; 24 sigset_t sigrtmin; 25 int err; 26 pid_t *tid = arg; 27 28 sigemptyset(&sigrtmin); 29 sigaddset(&sigrtmin, SIGRTMIN); 30 31 err = pthread_sigmask(SIG_BLOCK, &sigrtmin, NULL); 32 if (err) 33 tst_brk(TBROK, "pthread_sigmask() failed: %s", 34 tst_strerrno(err)); 35 36 SAFE_SETRLIMIT(RLIMIT_SIGPENDING, &sigpending); 37 *tid = sys_gettid(); 38 39 TST_CHECKPOINT_WAKE_AND_WAIT(0); 40 41 return arg; 42 } 43 44 static void run(void) 45 { 46 pthread_t thread; 47 pid_t tid = -1; 48 49 SAFE_PTHREAD_CREATE(&thread, NULL, thread_func, &tid); 50 51 TST_CHECKPOINT_WAIT(0); 52 53 TEST(sys_tgkill(getpid(), tid, SIGRTMIN)); 54 if (TST_RET && TST_ERR == EAGAIN) 55 tst_res(TPASS, "tgkill() failed with EAGAIN as expected"); 56 else 57 tst_res(TFAIL | TTERRNO, 58 "tgkill() should have failed with EAGAIN"); 59 60 TST_CHECKPOINT_WAKE(0); 61 62 SAFE_PTHREAD_JOIN(thread, NULL); 63 } 64 65 static struct tst_test test = { 66 .needs_checkpoints = 1, 67 .test_all = run, 68 }; 69