Skip to content

Commit 7eb33ab

Browse files
committed
Add test case for switching out of desched syscall
This adds a test case to model #3285, where the test case pokes the sigframe to force sigreturn to switch to a different function than that which incurred the signal.
1 parent 1cf85b7 commit 7eb33ab

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,7 @@ set(BASIC_TESTS
912912
daemon
913913
desched_blocking_poll
914914
desched_sigkill
915+
desched_sigreturn
915916
detach_state
916917
detach_threads
917918
detach_sigkill

src/test/desched_sigreturn.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
2+
3+
#include "util.h"
4+
5+
pid_t main_thread_tid = 0;
6+
int fds[2];
7+
char zeros[8192];
8+
9+
void sigproc_and_hang(void)
10+
{
11+
sigset_t sigs;
12+
sigfillset(&sigs);
13+
sigdelset(&sigs, SIGUSR2);
14+
sigprocmask(SIG_SETMASK, &sigs, NULL);
15+
write(fds[1], &zeros, 8192);
16+
write(fds[1], &zeros, 8192);
17+
test_assert(0);
18+
}
19+
20+
void print_and_exit(void)
21+
{
22+
atomic_printf("EXIT-SUCCESS\n");
23+
exit(0);
24+
}
25+
26+
volatile int counter = 0;
27+
void usr2_handler(__attribute__((unused)) int signum,
28+
__attribute__((unused)) siginfo_t* siginfo_ptr,
29+
void* ucontext_ptr) {
30+
uintptr_t target = counter == 0 ? (uintptr_t)&sigproc_and_hang : (uintptr_t)&print_and_exit;
31+
counter += 1;
32+
#if defined(__i386__)
33+
ucontext_t* ctx = (ucontext_t*)ucontext_ptr;
34+
ctx->uc_mcontext.gregs[REG_EIP] = (uint32_t)target;
35+
#elif defined(__x86_64__)
36+
ucontext_t* ctx = (ucontext_t*)ucontext_ptr;
37+
ctx->uc_mcontext.gregs[REG_RIP] = (long long)target;
38+
#elif defined(__aarch64__)
39+
ucontext_t* ctx = (ucontext_t*)ucontext_ptr;
40+
ctx->uc_mcontext.pc = (long)target;
41+
#else
42+
#error "Unsupported architecture"
43+
#endif
44+
}
45+
46+
static void* signaler_thread(__attribute__((unused)) void* p) {
47+
for (int i = 0; i < 10; ++i)
48+
sched_yield();
49+
syscall(SYS_tgkill, getpid(), main_thread_tid, SIGUSR2);
50+
// Technically should use atomics, but volatile is good enough for this test,
51+
// since we're doing a syscall in the loop.
52+
while (counter == 0)
53+
sched_yield();
54+
for (int i = 0; i < 10; ++i)
55+
sched_yield();
56+
syscall(SYS_tgkill, getpid(), main_thread_tid, SIGUSR2);
57+
return NULL;
58+
}
59+
60+
int main(void) {
61+
int err = pipe(fds);
62+
test_assert(err == 0);
63+
64+
err = fcntl(fds[1], F_SETPIPE_SZ, 4096);
65+
test_assert(err > 0);
66+
67+
struct sigaction sa;
68+
memset(&sa, 0, sizeof(sa));
69+
sa.sa_sigaction = usr2_handler;
70+
sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTART;
71+
err = sigaction(SIGUSR2, &sa, NULL);
72+
test_assert(err == 0);
73+
74+
main_thread_tid = sys_gettid();
75+
76+
pthread_t thread;
77+
pthread_create(&thread, NULL, signaler_thread, NULL);
78+
79+
// Block on pipe read.
80+
int ch = 0;
81+
err = read(fds[0], &ch, sizeof(int));
82+
test_assert(0);
83+
84+
return 0;
85+
}

0 commit comments

Comments
 (0)