• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
thread_func(void * arg)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 
run(void)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