DragonOS/user/apps/c_unitest/test_wait_wnothread.c

90 lines
1.9 KiB
C

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
static pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cv_child_ready = PTHREAD_COND_INITIALIZER;
static pthread_cond_t cv_main_done = PTHREAD_COND_INITIALIZER;
static pid_t g_child_pid = 0;
static int g_main_done = 0;
static void *forker_thread(void *arg) {
(void)arg;
pid_t pid = fork();
if (pid < 0) {
perror("fork");
_exit(2);
}
if (pid == 0) {
sleep(3);
_exit(0);
}
pthread_mutex_lock(&mu);
g_child_pid = pid;
pthread_cond_broadcast(&cv_child_ready);
while (!g_main_done) {
pthread_cond_wait(&cv_main_done, &mu);
}
pthread_mutex_unlock(&mu);
int status = 0;
pid_t got = wait4(-1, &status, __WNOTHREAD, NULL);
if (got < 0) {
perror("wait4(__WNOTHREAD) in forker thread");
_exit(3);
}
if (got != pid) {
fprintf(stderr, "wait4 returned %d, expected %d\n", got, pid);
_exit(4);
}
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
fprintf(stderr, "child status unexpected: 0x%x\n", status);
_exit(5);
}
return NULL;
}
int main(void) {
pthread_t th;
if (pthread_create(&th, NULL, forker_thread, NULL) != 0) {
perror("pthread_create");
return 1;
}
pthread_mutex_lock(&mu);
while (g_child_pid == 0) {
pthread_cond_wait(&cv_child_ready, &mu);
}
pthread_mutex_unlock(&mu);
alarm(5);
int status = 0;
pid_t got = wait4(-1, &status, __WNOTHREAD, NULL);
if (got != -1 || errno != ECHILD) {
fprintf(stderr, "main wait4 expected -1/ECHILD, got=%d errno=%d\n", got,
errno);
return 2;
}
pthread_mutex_lock(&mu);
g_main_done = 1;
pthread_cond_broadcast(&cv_main_done);
pthread_mutex_unlock(&mu);
if (pthread_join(th, NULL) != 0) {
perror("pthread_join");
return 3;
}
printf("test_wait_wnothread: PASS\n");
return 0;
}