From 75b0c6fc91c1264aaa5d080d9faeb87c90d02ad3 Mon Sep 17 00:00:00 2001 From: Robert Morris Date: Fri, 5 Jul 2019 12:33:26 -0400 Subject: [PATCH] back-port fork/exit/exit tests to xv6-riscv --- user/cow.c | 2 +- user/init.c | 5 ++- user/usertests.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/user/cow.c b/user/cow.c index 45efc98..0426600 100644 --- a/user/cow.c +++ b/user/cow.c @@ -129,7 +129,7 @@ filetest() { int parent = getpid(); - printf(1, "file test: "); + printf(1, "file: "); buf[0] = 99; diff --git a/user/init.c b/user/init.c index f36ba31..03e60da 100644 --- a/user/init.c +++ b/user/init.c @@ -31,7 +31,8 @@ main(void) printf(1, "init: exec sh failed\n"); exit(); } - while((wpid=wait()) >= 0 && wpid != pid) - printf(1, "zombie!\n"); + while((wpid=wait()) >= 0 && wpid != pid){ + //printf(1, "zombie!\n"); + } } } diff --git a/user/usertests.c b/user/usertests.c index ef70bfb..9d46b1a 100644 --- a/user/usertests.c +++ b/user/usertests.c @@ -417,16 +417,18 @@ exitwait(void) { int i, pid; + printf(1, "exitwait test\n"); + for(i = 0; i < 100; i++){ pid = fork(); if(pid < 0){ printf(1, "fork failed\n"); - return; + exit(); } if(pid){ if(wait() != pid){ printf(1, "wait wrong pid\n"); - return; + exit(); } } else { exit(); @@ -435,6 +437,109 @@ exitwait(void) printf(1, "exitwait ok\n"); } +// try to find races in the reparenting +// code that handles a parent exiting +// when it still has live children. +void +reparent(void) +{ + int master_pid = getpid(); + + printf(1, "reparent test\n"); + + for(int i = 0; i < 100; i++){ + int pid = fork(); + if(pid < 0){ + printf(1, "fork failed\n"); + exit(); + } + if(pid){ + if(wait() != pid){ + printf(1, "wait wrong pid\n"); + exit(); + } + } else { + int pid2 = fork(); + if(pid2 < 0){ + printf(1, "fork failed\n"); + kill(master_pid); + exit(); + } + if(pid2 == 0){ + exit(); + } else { + exit(); + } + } + } + printf(1, "reparent ok\n"); +} + +// what if two children exit() at the same time? +void +twochildren(void) +{ + printf(1, "twochildren test\n"); + + for(int i = 0; i < 1000; i++){ + int pid1 = fork(); + if(pid1 < 0){ + printf(1, "fork failed\n"); + exit(); + } + if(pid1 == 0){ + exit(); + } else { + int pid2 = fork(); + if(pid2 < 0){ + printf(1, "fork failed\n"); + exit(); + } + if(pid2 == 0){ + exit(); + } else { + wait(); + wait(); + } + } + } + printf(1, "twochildren ok\n"); +} + +void +forkforkfork(void) +{ + printf(1, "forkforkfork test\n"); + + unlink("stopforking"); + + int pid = fork(); + if(pid < 0){ + printf(1, "fork failed"); + exit(); + } + if(pid == 0){ + while(1){ + int fd = open("stopforking", 0); + if(fd >= 0){ + exit(); + } + if(fork() < 0){ + close(open("stopforking", O_CREATE|O_RDWR)); + } + } + + exit(); + } + + sleep(2); + close(open("stopforking", O_CREATE|O_RDWR)); + wait(); + sleep(1); + + printf(1, "forkforkfork ok\n"); +} + void mem(void) { @@ -1751,6 +1856,10 @@ main(int argc, char *argv[]) } close(open("usertests.ran", O_CREATE)); + reparent(); + twochildren(); + forkforkfork(); + argptest(); createdelete(); linkunlink();