1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2018 Google, Inc.
4*49cdfc7eSAndroid Build Coastguard Worker *
5*49cdfc7eSAndroid Build Coastguard Worker * Test simple tgkill() error cases.
6*49cdfc7eSAndroid Build Coastguard Worker */
7*49cdfc7eSAndroid Build Coastguard Worker
8*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
9*49cdfc7eSAndroid Build Coastguard Worker #include <pwd.h>
10*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
12*49cdfc7eSAndroid Build Coastguard Worker
13*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_pthread.h"
14*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
15*49cdfc7eSAndroid Build Coastguard Worker #include "tgkill.h"
16*49cdfc7eSAndroid Build Coastguard Worker
17*49cdfc7eSAndroid Build Coastguard Worker #define CHECK_ENOENT(x) ((x) == -1 && errno == ENOENT)
18*49cdfc7eSAndroid Build Coastguard Worker
19*49cdfc7eSAndroid Build Coastguard Worker static pthread_t child_thread;
20*49cdfc7eSAndroid Build Coastguard Worker
21*49cdfc7eSAndroid Build Coastguard Worker static pid_t parent_tgid;
22*49cdfc7eSAndroid Build Coastguard Worker static pid_t parent_tid;
23*49cdfc7eSAndroid Build Coastguard Worker static pid_t child_tid;
24*49cdfc7eSAndroid Build Coastguard Worker static pid_t defunct_tid;
25*49cdfc7eSAndroid Build Coastguard Worker
26*49cdfc7eSAndroid Build Coastguard Worker static const int invalid_pid = -1;
27*49cdfc7eSAndroid Build Coastguard Worker
child_thread_func(void * arg)28*49cdfc7eSAndroid Build Coastguard Worker static void *child_thread_func(void *arg)
29*49cdfc7eSAndroid Build Coastguard Worker {
30*49cdfc7eSAndroid Build Coastguard Worker child_tid = sys_gettid();
31*49cdfc7eSAndroid Build Coastguard Worker
32*49cdfc7eSAndroid Build Coastguard Worker TST_CHECKPOINT_WAKE_AND_WAIT(0);
33*49cdfc7eSAndroid Build Coastguard Worker
34*49cdfc7eSAndroid Build Coastguard Worker return arg;
35*49cdfc7eSAndroid Build Coastguard Worker }
36*49cdfc7eSAndroid Build Coastguard Worker
defunct_thread_func(void * arg)37*49cdfc7eSAndroid Build Coastguard Worker static void *defunct_thread_func(void *arg)
38*49cdfc7eSAndroid Build Coastguard Worker {
39*49cdfc7eSAndroid Build Coastguard Worker defunct_tid = sys_gettid();
40*49cdfc7eSAndroid Build Coastguard Worker
41*49cdfc7eSAndroid Build Coastguard Worker return arg;
42*49cdfc7eSAndroid Build Coastguard Worker }
43*49cdfc7eSAndroid Build Coastguard Worker
setup(void)44*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
45*49cdfc7eSAndroid Build Coastguard Worker {
46*49cdfc7eSAndroid Build Coastguard Worker sigset_t sigusr1;
47*49cdfc7eSAndroid Build Coastguard Worker pthread_t defunct_thread;
48*49cdfc7eSAndroid Build Coastguard Worker char defunct_tid_path[PATH_MAX];
49*49cdfc7eSAndroid Build Coastguard Worker int ret;
50*49cdfc7eSAndroid Build Coastguard Worker
51*49cdfc7eSAndroid Build Coastguard Worker sigemptyset(&sigusr1);
52*49cdfc7eSAndroid Build Coastguard Worker sigaddset(&sigusr1, SIGUSR1);
53*49cdfc7eSAndroid Build Coastguard Worker pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);
54*49cdfc7eSAndroid Build Coastguard Worker
55*49cdfc7eSAndroid Build Coastguard Worker parent_tgid = getpid();
56*49cdfc7eSAndroid Build Coastguard Worker parent_tid = sys_gettid();
57*49cdfc7eSAndroid Build Coastguard Worker
58*49cdfc7eSAndroid Build Coastguard Worker SAFE_PTHREAD_CREATE(&child_thread, NULL, child_thread_func, NULL);
59*49cdfc7eSAndroid Build Coastguard Worker
60*49cdfc7eSAndroid Build Coastguard Worker TST_CHECKPOINT_WAIT(0);
61*49cdfc7eSAndroid Build Coastguard Worker
62*49cdfc7eSAndroid Build Coastguard Worker SAFE_PTHREAD_CREATE(&defunct_thread, NULL, defunct_thread_func, NULL);
63*49cdfc7eSAndroid Build Coastguard Worker SAFE_PTHREAD_JOIN(defunct_thread, NULL);
64*49cdfc7eSAndroid Build Coastguard Worker sprintf(defunct_tid_path, "/proc/%d/task/%d", getpid(), defunct_tid);
65*49cdfc7eSAndroid Build Coastguard Worker ret = TST_RETRY_FN_EXP_BACKOFF(access(defunct_tid_path, R_OK),
66*49cdfc7eSAndroid Build Coastguard Worker CHECK_ENOENT, 15);
67*49cdfc7eSAndroid Build Coastguard Worker if (!CHECK_ENOENT(ret))
68*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Timeout, %s still exists", defunct_tid_path);
69*49cdfc7eSAndroid Build Coastguard Worker }
70*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)71*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
72*49cdfc7eSAndroid Build Coastguard Worker {
73*49cdfc7eSAndroid Build Coastguard Worker TST_CHECKPOINT_WAKE(0);
74*49cdfc7eSAndroid Build Coastguard Worker
75*49cdfc7eSAndroid Build Coastguard Worker SAFE_PTHREAD_JOIN(child_thread, NULL);
76*49cdfc7eSAndroid Build Coastguard Worker }
77*49cdfc7eSAndroid Build Coastguard Worker
78*49cdfc7eSAndroid Build Coastguard Worker static const struct testcase {
79*49cdfc7eSAndroid Build Coastguard Worker const char *desc;
80*49cdfc7eSAndroid Build Coastguard Worker const int *tgid;
81*49cdfc7eSAndroid Build Coastguard Worker const int *tid;
82*49cdfc7eSAndroid Build Coastguard Worker const int sig;
83*49cdfc7eSAndroid Build Coastguard Worker const int err;
84*49cdfc7eSAndroid Build Coastguard Worker } testcases[] = {
85*49cdfc7eSAndroid Build Coastguard Worker { "Invalid tgid", &invalid_pid, &parent_tid, SIGUSR1, EINVAL },
86*49cdfc7eSAndroid Build Coastguard Worker { "Invalid tid", &parent_tgid, &invalid_pid, SIGUSR1, EINVAL },
87*49cdfc7eSAndroid Build Coastguard Worker { "Invalid signal", &parent_tgid, &parent_tid, -1, EINVAL },
88*49cdfc7eSAndroid Build Coastguard Worker { "Defunct tid", &parent_tgid, &defunct_tid, SIGUSR1, ESRCH },
89*49cdfc7eSAndroid Build Coastguard Worker { "Defunct tgid", &defunct_tid, &child_tid, SIGUSR1, ESRCH },
90*49cdfc7eSAndroid Build Coastguard Worker { "Valid tgkill call", &parent_tgid, &child_tid, SIGUSR1, 0 },
91*49cdfc7eSAndroid Build Coastguard Worker };
92*49cdfc7eSAndroid Build Coastguard Worker
run(unsigned int i)93*49cdfc7eSAndroid Build Coastguard Worker static void run(unsigned int i)
94*49cdfc7eSAndroid Build Coastguard Worker {
95*49cdfc7eSAndroid Build Coastguard Worker const struct testcase *tc = &testcases[i];
96*49cdfc7eSAndroid Build Coastguard Worker
97*49cdfc7eSAndroid Build Coastguard Worker TEST(sys_tgkill(*tc->tgid, *tc->tid, tc->sig));
98*49cdfc7eSAndroid Build Coastguard Worker if (tc->err) {
99*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET < 0 && TST_ERR == tc->err)
100*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS | TTERRNO, "%s failed as expected",
101*49cdfc7eSAndroid Build Coastguard Worker tc->desc);
102*49cdfc7eSAndroid Build Coastguard Worker else
103*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL | TTERRNO,
104*49cdfc7eSAndroid Build Coastguard Worker "%s should have failed with %s", tc->desc,
105*49cdfc7eSAndroid Build Coastguard Worker tst_strerrno(tc->err));
106*49cdfc7eSAndroid Build Coastguard Worker } else {
107*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET == 0)
108*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "%s succeeded", tc->desc);
109*49cdfc7eSAndroid Build Coastguard Worker else
110*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL | TTERRNO, "%s failed", tc->desc);
111*49cdfc7eSAndroid Build Coastguard Worker }
112*49cdfc7eSAndroid Build Coastguard Worker }
113*49cdfc7eSAndroid Build Coastguard Worker
114*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
115*49cdfc7eSAndroid Build Coastguard Worker .tcnt = ARRAY_SIZE(testcases),
116*49cdfc7eSAndroid Build Coastguard Worker .needs_checkpoints = 1,
117*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
118*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
119*49cdfc7eSAndroid Build Coastguard Worker .test = run,
120*49cdfc7eSAndroid Build Coastguard Worker };
121