The Pedigree Project 0.1
child-wait-contract-test/events.c
1#define _GNU_SOURCE
2#include <string.h>
3#include <unistd.h>
4
5#include "contract.h"
6
7int cw_events(void) {
8 int failed = 0, status;
9 struct cw_child child = CW_CHILD_INIT, killed = CW_CHILD_INIT;
10 siginfo_t info;
11 CHECK(cw_spawn(&child, -1, (uid_t)-1, 47) == 0);
12 CHECK(cw_send(child.command, 'S') == 0);
13 for (int i = 0; i < 3; ++i) {
14 CHECK(waitid(P_PID, child.pid, &info, WSTOPPED | WNOWAIT) == 0);
15 CHECK(cw_info(&info, child.pid, getuid(), CLD_STOPPED, SIGSTOP) == 0);
16 }
17 memset(&info, 0xa5, sizeof(info));
18 CHECK(waitid(P_PID, child.pid, &info, WEXITED | WNOHANG) == 0 && !cw_empty_info(&info));
19 CHECK(waitpid(child.pid, &status, WUNTRACED) == child.pid);
20 CHECK(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);
21 CHECK(waitid(P_PID, child.pid, &info, WSTOPPED | WNOHANG) == 0 && !cw_empty_info(&info));
22
23 CHECK(kill(child.pid, SIGCONT) == 0 && cw_receive(child.report, 'C') == 0);
24 for (int i = 0; i < 3; ++i) {
25 CHECK(waitid(P_PID, child.pid, &info, WCONTINUED | WNOWAIT) == 0);
26 CHECK(cw_info(&info, child.pid, getuid(), CLD_CONTINUED, SIGCONT) == 0);
27 }
28 CHECK(waitid(P_PID, child.pid, &info, WSTOPPED | WNOHANG) == 0 && !cw_empty_info(&info));
29 CHECK(waitid(P_PID, child.pid, &info, WCONTINUED) == 0);
30 CHECK(cw_info(&info, child.pid, getuid(), CLD_CONTINUED, SIGCONT) == 0);
31 CHECK(waitpid(child.pid, &status, WCONTINUED | WNOHANG) == 0);
32
33 CHECK(cw_send(child.command, 'S') == 0);
34 CHECK(waitid(P_PID, child.pid, &info, WSTOPPED) == 0);
35 CHECK(cw_info(&info, child.pid, getuid(), CLD_STOPPED, SIGSTOP) == 0);
36 CHECK(kill(child.pid, SIGCONT) == 0 && cw_receive(child.report, 'C') == 0);
37 CHECK(wait4(child.pid, &status, WCONTINUED, NULL) == child.pid && WIFCONTINUED(status));
38 CHECK(cw_send(child.command, 'E') == 0);
39 CHECK(waitid(P_PID, child.pid, &info, WEXITED | WNOWAIT) == 0);
40 memset(&info, 0xa5, sizeof(info));
41 CHECK(waitid(P_PID, child.pid, &info, WSTOPPED | WNOHANG) == -1 && errno == ECHILD);
42 CHECK(!cw_empty_info(&info));
43 memset(&info, 0xa5, sizeof(info));
44 CHECK(waitid(P_PID, child.pid, &info, WCONTINUED | WNOHANG) == -1 && errno == ECHILD);
45 CHECK(!cw_empty_info(&info));
46 CHECK(waitid(P_PID, child.pid, &info, WEXITED) == 0);
47 CHECK(cw_info(&info, child.pid, getuid(), CLD_EXITED, 47) == 0);
48 child.pid = -1;
49
50 CHECK(cw_spawn(&killed, -1, (uid_t)-1, 0) == 0);
51 CHECK(kill(killed.pid, SIGTERM) == 0);
52 CHECK(waitid(P_PID, killed.pid, &info, WEXITED | WNOWAIT) == 0);
53 CHECK(cw_info(&info, killed.pid, getuid(), CLD_KILLED, SIGTERM) == 0);
54 CHECK(waitpid(killed.pid, &status, 0) == killed.pid);
55 CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM && !WCOREDUMP(status));
56 killed.pid = -1;
57out:
58 cw_cleanup(&killed);
59 cw_cleanup(&child);
60 return failed;
61}