-
Notifications
You must be signed in to change notification settings - Fork 599
/
Copy pathsigcont_threaded.c
63 lines (51 loc) · 1.58 KB
/
sigcont_threaded.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
#include "util.h"
static void *child_process_extra_thread(__attribute__((unused)) void *extra_thread) {
int r;
// Slap in a sched_yield or two here so that the parent process is going to be
// blocked in pthread_join.
sched_yield();
sched_yield();
// Now, stop ourselves. We'll be unstopped by the parent process.
r = kill(gettid(), SIGSTOP);
test_assert(r == 0);
// Now allow self to exit, and the thread-group-leader can continue.
return NULL;
}
static void child_process(void) {
pthread_t extra_thread;
int r;
// Spawn an additional thread
r = pthread_create(&extra_thread, NULL, child_process_extra_thread, NULL);
test_assert(r == 0);
// Wait for the child thread we made. It will send SIGSTOP to the process.
r = pthread_join(extra_thread, NULL);
test_assert(r == 0);
}
static void parent_process(pid_t pid) {
int wait_status, r;
pid_t wpid;
// Wait for the child process to have sent itself SIGSTOP
wpid = waitpid(pid, &wait_status, WUNTRACED);
test_assert(wpid == pid);
test_assert(WIFSTOPPED(wait_status));
test_assert(WSTOPSIG(wait_status) == SIGSTOP);
// Let it continue
r = kill(pid, SIGCONT);
test_assert(r == 0);
// Now the child process should actually exit
wpid = waitpid(pid, &wait_status, 0);
test_assert(wpid == pid);
test_assert(WIFEXITED(wait_status));
}
int main(void) {
pid_t pid = fork();
test_assert(pid != -1);
if (pid == 0) {
child_process();
} else {
parent_process(pid);
atomic_puts("EXIT-SUCCESS");
}
return 0;
}