14long long test_milliseconds(
void) {
16 if (clock_gettime(CLOCK_MONOTONIC, &now)) {
19 return (
long long)now.tv_sec * 1000 + now.tv_nsec / 1000000;
22int test_wait_flag(
volatile int* flag) {
23 const long long start = test_milliseconds();
27 while (!__atomic_load_n(flag, __ATOMIC_ACQUIRE)) {
28 const long long now = test_milliseconds();
29 if (now < 0 || now - start >= 3000) {
37void test_pause(
void) {
38 struct timespec delay = {.tv_nsec = 2000000};
39 while (nanosleep(&delay, &delay) && errno == EINTR) {
43static int run_bounded(
const char* program,
const char* name) {
44 printf(
"SIGNAL-EXEC-TEST: BEGIN %s\n", name);
46 const pid_t child = fork();
53 !strncmp(name,
"exec-", 5) ? exec_contract(program, name) : signal_contract(name);
58 const long long start = test_milliseconds();
60 const pid_t waited = waitpid(child, &status, WNOHANG);
61 if (waited == child) {
62 return WIFEXITED(status) ? WEXITSTATUS(status) : 128 + WTERMSIG(status);
64 if (waited < 0 && errno != EINTR) {
67 const long long now = test_milliseconds();
68 if (now < 0 || now - start >= 15000) {
73 (void)kill(child, SIGKILL);
74 while (waitpid(child, &status, 0) < 0 && errno == EINTR) {
79int main(
int argc,
char* argv[]) {
81 (!strcmp(argv[1],
"--exec-image") || !strcmp(argv[1],
"--exec-race-image") ||
82 !strcmp(argv[1],
"--exec-pending-image") || !strcmp(argv[1],
"--exec-exit-image"))) {
83 return exec_image_contract(argc, argv);
86 const char* cases[] = {
87 "read-eintr",
"read-restart",
"wait-eintr",
"wait-restart",
88 "partial-write",
"nanosleep-eintr",
"ppoll-eintr",
"pselect-eintr",
89 "epoll-eintr",
"reset-hand",
"exec-main",
"exec-worker",
90 "exec-failure",
"futex-eintr",
"futex-restart",
"exec-race",
91 "exec-pending-main",
"exec-pending-worker",
"exec-exit-race",
"sigsuspend-eintr"};
93 for (
size_t i = 0; i <
sizeof(cases) /
sizeof(cases[0]); ++i) {
94 if (argc > 1 && strcmp(argv[1], cases[i])) {
98 const int exit_race = !strcmp(cases[i],
"exec-exit-race");
99 for (
int iteration = 0; iteration < (exit_race ? 3 : 1); ++iteration) {
100 const int result = run_bounded(argv[0], cases[i]);
101 if (result && !(exit_race && result == 37)) {
102 printf(
"SIGNAL-EXEC-TEST: FAIL %s code=%d\n", cases[i], result);
103 puts(
"SIGNAL-EXEC-TEST: END FAIL");
107 printf(
"SIGNAL-EXEC-TEST: EXIT-RACE iteration=%d code=%d\n", iteration + 1, result);
110 printf(
"SIGNAL-EXEC-TEST: PASS %s\n", cases[i]);
114 fprintf(stderr,
"Unknown signal/exec test: %s\n", argv[1]);
117 puts(
"SIGNAL-EXEC-TEST: PASS");
118 puts(
"SIGNAL-EXEC-TEST: END PASS");