• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2019 SUSE LLC
4  * Author: Christian Amann <camann@suse.com>
5  */
6 
7 /*
8  * This tests the rt_sigqueueinfo() syscall.
9  *
10  * It does so by creating a thread which registers the corresponding
11  * signal handler. After that the main thread sends a signal and data
12  * to the handler thread. If the correct signal and data is received,
13  * the test is successful.
14  */
15 
16 #include <signal.h>
17 #include <stdlib.h>
18 #include "config.h"
19 #include "tst_test.h"
20 #include "tst_safe_pthread.h"
21 
22 #ifdef HAVE_STRUCT_SIGACTION_SA_SIGACTION
23 #include "rt_sigqueueinfo.h"
24 
25 #define SIGNAL	SIGUSR1
26 #define DATA	777
27 
28 static struct sigaction *sig_action;
29 static int sig_rec;
30 static siginfo_t *uinfo;
31 static pid_t tid;
32 
received_signal(int sig,siginfo_t * info,void * ucontext)33 static void received_signal(int sig, siginfo_t *info, void *ucontext)
34 {
35 	if (info && ucontext) {
36 		if (sig == SIGNAL && info->si_value.sival_int == DATA) {
37 			tst_res(TPASS, "Received correct signal and data!");
38 			sig_rec = 1;
39 		} else
40 			tst_res(TFAIL, "Received wrong signal and/or data!");
41 	} else
42 		tst_res(TFAIL, "Signal handling went wrong!");
43 }
44 
handle_thread(void * arg LTP_ATTRIBUTE_UNUSED)45 static void *handle_thread(void *arg LTP_ATTRIBUTE_UNUSED)
46 {
47 	int ret;
48 
49 	tid = tst_syscall(__NR_gettid);
50 
51 	ret = sigaction(SIGNAL, sig_action, NULL);
52 	if (ret)
53 		tst_brk(TBROK, "Failed to set sigaction for handler thread!");
54 
55 	TST_CHECKPOINT_WAKE(0);
56 	TST_CHECKPOINT_WAIT(1);
57 	return arg;
58 }
59 
verify_sigqueueinfo(void)60 static void verify_sigqueueinfo(void)
61 {
62 	pthread_t thr;
63 
64 	SAFE_PTHREAD_CREATE(&thr, NULL, handle_thread, NULL);
65 
66 	TST_CHECKPOINT_WAIT(0);
67 
68 	TEST(sys_rt_sigqueueinfo(tid, SIGNAL, uinfo));
69 	if (TST_RET != 0) {
70 		tst_res(TFAIL | TTERRNO, "rt_sigqueueinfo() failed");
71 		return;
72 	}
73 
74 	TST_CHECKPOINT_WAKE(1);
75 	SAFE_PTHREAD_JOIN(thr, NULL);
76 
77 	if (sig_rec)
78 		tst_res(TPASS, "rt_sigqueueinfo() was successful!");
79 }
80 
setup(void)81 static void setup(void)
82 {
83 	sig_action = SAFE_MALLOC(sizeof(struct sigaction));
84 
85 	memset(sig_action, 0, sizeof(*sig_action));
86 	sig_action->sa_sigaction = received_signal;
87 	sig_action->sa_flags = SA_SIGINFO;
88 
89 	uinfo = SAFE_MALLOC(sizeof(siginfo_t));
90 
91 	memset(uinfo, 0, sizeof(*uinfo));
92 	uinfo->si_code = SI_QUEUE;
93 	uinfo->si_pid = getpid();
94 	uinfo->si_uid = getuid();
95 	uinfo->si_value.sival_int = DATA;
96 
97 	sig_rec = 0;
98 }
99 
cleanup(void)100 static void cleanup(void)
101 {
102 	free(uinfo);
103 	free(sig_action);
104 }
105 
106 static struct tst_test test = {
107 	.test_all = verify_sigqueueinfo,
108 	.setup = setup,
109 	.cleanup = cleanup,
110 	.needs_checkpoints = 1,
111 	.timeout = 20,
112 };
113 
114 #else
115 	TST_TEST_TCONF(
116 		"This system does not support rt_sigqueueinfo().");
117 #endif /* HAVE_STRUCT_SIGACTION_SA_SIGACTION */
118