1 /*
2 * Check decoding of rt_sigpending syscall.
3 *
4 * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2016-2021 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include "scno.h"
13
14 #include <assert.h>
15 #include <signal.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19
20 static long
21 k_sigpending(void *const set, const unsigned long size)
22 {
23 return syscall(__NR_rt_sigpending, set, size);
24 }
25
26 static void
27 iterate(const char *const text, unsigned int size, void *set)
28 {
29 for (;;) {
30 if (k_sigpending(set, size)) {
31 tprintf("rt_sigpending(%p, %u) = -1 EFAULT (%m)\n",
32 set, size);
33 break;
34 }
35 if (size) {
36 #ifdef WORDS_BIGENDIAN
37 if (size < sizeof(long))
38 tprintf("rt_sigpending(%s, %u) = 0\n",
39 "[]", size);
40 else
41 #endif
42 tprintf("rt_sigpending(%s, %u) = 0\n",
43 text, size);
44 } else {
45 tprintf("rt_sigpending(%p, %u) = 0\n", set, size);
46 break;
47 }
48 size >>= 1;
49 set += size;
50 }
51 }
52
53 int
54 main(void)
55 {
56 tprintf("%s", "");
57
58 const unsigned int big_size = 1024 / 8;
59 void *k_set = tail_alloc(big_size);
60 TAIL_ALLOC_OBJECT_CONST_PTR(sigset_t, libc_set);
61
62 sigemptyset(libc_set);
63 if (sigprocmask(SIG_SETMASK, libc_set, NULL))
64 perror_msg_and_fail("sigprocmask");
65
66 memset(k_set, 0, big_size);
67 unsigned int set_size = big_size;
68 for (; set_size; set_size >>= 1, k_set += set_size) {
69 if (!k_sigpending(k_set, set_size))
70 break;
71 tprintf("rt_sigpending(%p, %u) = -1 EINVAL (%m)\n",
72 k_set, set_size);
73 }
74 if (!set_size)
75 perror_msg_and_fail("rt_sigpending");
76 tprintf("rt_sigpending(%s, %u) = 0\n", "[]", set_size);
77
78 iterate("[]", set_size >> 1, k_set + (set_size >> 1));
79
80 void *const efault = k_set + (set_size >> 1);
81 assert(k_sigpending(efault, set_size) == -1);
82 tprintf("rt_sigpending(%p, %u) = -1 EFAULT (%m)\n",
83 efault, set_size);
84
85 sigaddset(libc_set, SIGHUP);
86 if (sigprocmask(SIG_SETMASK, libc_set, NULL))
87 perror_msg_and_fail("sigprocmask");
88 raise(SIGHUP);
89
90 iterate("[HUP]", set_size, k_set);
91
92 sigaddset(libc_set, SIGINT);
93 if (sigprocmask(SIG_SETMASK, libc_set, NULL))
94 perror_msg_and_fail("sigprocmask");
95 raise(SIGINT);
96
97 iterate("[HUP INT]", set_size, k_set);
98
99 tprintf("+++ exited with 0 +++\n");
100 return 0;
101 }