occlum/test/wait/main.c
2021-05-10 10:11:24 +08:00

104 lines
3.0 KiB
C

#define _GNU_SOURCE
#include <sys/wait.h>
#include <errno.h>
#include <spawn.h>
#include <stdbool.h>
#include <stdlib.h>
#include "test.h"
static int test_wait_no_children() {
int status = 0;
int ret = wait(&status);
if (ret != -1 || errno != ECHILD) {
THROW_ERROR("wait no children error");
}
return 0;
}
static int test_wait_nohang() {
int status = 0;
int ret = waitpid(-1, &status, WNOHANG);
if (ret != -1 || errno != ECHILD) {
THROW_ERROR("wait no children with NOHANG error");
}
int child_pid = 0;
// /bin/sleep lasts more than 1 sec
if (posix_spawn(&child_pid, "/bin/sleep", NULL, NULL, NULL, NULL) < 0) {
THROW_ERROR("posix_spawn child error");
}
ret = waitpid(child_pid, &status, WNOHANG);
if (ret != 0) {
THROW_ERROR("wait child with NOHANG error");
}
sleep(2);
// The child process should exit
ret = waitpid(child_pid, &status, WNOHANG);
if (ret != child_pid) {
THROW_ERROR("wait child with NOHANG error");
}
return 0;
}
// NOTE: WUNTRACED is same as WSTOPPED
// TODO: Support WUNTRACED and WCONTINUED and enable this test case
static int test_wait_untraced_and_continued() {
int status = 0;
int ret = waitpid(-1, &status, WNOHANG);
if (ret != -1 || errno != ECHILD) {
THROW_ERROR("wait no children with NOHANG error");
}
int child_pid = 0;
if (posix_spawn(&child_pid, "/bin/sleep", NULL, NULL, NULL, NULL) < 0) {
THROW_ERROR("posix_spawn child error");
}
ret = waitpid(child_pid, &status, WNOHANG);
if (ret != 0) {
THROW_ERROR("wait child with NOHANG error");
}
kill(child_pid, SIGSTOP);
// WUNTRACED will get child_pid status
ret = waitpid(child_pid, &status, WUNTRACED);
printf("ret = %d, status = %d\n", ret, status);
if (ret != child_pid || !WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP ) {
THROW_ERROR("wait child status error");
}
// Let child get back to running by sending SIGCONT
kill(child_pid, SIGCONT);
ret = waitpid(child_pid, &status, WCONTINUED);
printf("ret = %d, status = %d\n", ret, status);
if (ret != child_pid || !WIFCONTINUED(status)) {
THROW_ERROR("wait child status error");
}
sleep(2);
// The child process should exit
ret = waitpid(child_pid, &status, WNOHANG | WUNTRACED);
printf("ret = %d, status = %d\n", ret, status);
if (ret != child_pid || !WIFEXITED(status) ) {
THROW_ERROR("wait child with NOHANG error");
}
return 0;
}
// ============================================================================
// Test suite main
// ============================================================================
static test_case_t test_cases[] = {
TEST_CASE(test_wait_no_children),
TEST_CASE(test_wait_nohang),
// TODO: Enable this test case
// TEST_CASE(test_wait_untraced_and_continued),
};
int main(int argc, const char *argv[]) {
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
}