summaryrefslogtreecommitdiff
path: root/user/usertests.c
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2019-09-23 06:50:25 -0400
committerRobert Morris <[email protected]>2019-09-23 06:50:25 -0400
commitd175beadf5f009d0fb8881e32c913b1bc175c9f6 (patch)
treefcb8129eea981362de151f85bb185a4575b6e71d /user/usertests.c
parent843ce7776568ac2d4f71886e95077709b83bc613 (diff)
downloadxv6-labs-d175beadf5f009d0fb8881e32c913b1bc175c9f6.tar.gz
xv6-labs-d175beadf5f009d0fb8881e32c913b1bc175c9f6.tar.bz2
xv6-labs-d175beadf5f009d0fb8881e32c913b1bc175c9f6.zip
bug fix: reparent() sometimes deadlocked
bug fix: exit() sometimes released a different parent lock than it acquired usertests
Diffstat (limited to 'user/usertests.c')
-rw-r--r--user/usertests.c55
1 files changed, 39 insertions, 16 deletions
diff --git a/user/usertests.c b/user/usertests.c
index fe3ae49..db9f680 100644
--- a/user/usertests.c
+++ b/user/usertests.c
@@ -598,6 +598,31 @@ forkforkfork(char *s)
sleep(10); // one second
}
+// regression test. does reparent() violate the parent-then-child
+// locking order when giving away a child to init, so that exit()
+// deadlocks against init's wait()? also used to trigger a "panic:
+// release" due to exit() releasing a different p->parent->lock than
+// it acquired.
+void
+reparent2(char *s)
+{
+ for(int i = 0; i < 800; i++){
+ int pid1 = fork();
+ if(pid1 < 0){
+ printf("fork failed\n");
+ exit(1);
+ }
+ if(pid1 == 0){
+ fork();
+ fork();
+ exit(0);
+ }
+ wait(0);
+ }
+
+ exit(0);
+}
+
// allocate all mem, free it, and allocate again
void
mem(char *s)
@@ -1937,9 +1962,9 @@ stacktest(char *s)
exit(xstatus);
}
-// copyin(), copyout(), and copyinstr() used to cast the virtual page
-// address to uint, which (with certain wild system call arguments)
-// resulted in a kernel page faults.
+// regression test. copyin(), copyout(), and copyinstr() used to cast
+// the virtual page address to uint, which (with certain wild system
+// call arguments) resulted in a kernel page faults.
void
pgbug(char *s)
{
@@ -1952,9 +1977,9 @@ pgbug(char *s)
exit(0);
}
-// does the kernel panic if a process sbrk()s its size to be less than
-// a page, or zero, or reduces the break by an amount too small to
-// cause a page to be freed?
+// regression test. does the kernel panic if a process sbrk()s its
+// size to be less than a page, or zero, or reduces the break by an
+// amount too small to cause a page to be freed?
void
sbrkbugs(char *s)
{
@@ -2010,13 +2035,11 @@ sbrkbugs(char *s)
exit(0);
}
-// does write() with an invalid buffer pointer cause
-// a block to be allocated for a file that is then
-// not freed when the file is deleted? if the kernel
-// has this bug, it will panic: balloc: out of blocks.
-// assumed_free may need to be raised to be
-// more than the number of free blocks.
-// this test takes a long time.
+// regression test. does write() with an invalid buffer pointer cause
+// a block to be allocated for a file that is then not freed when the
+// file is deleted? if the kernel has this bug, it will panic: balloc:
+// out of blocks. assumed_free may need to be raised to be more than
+// the number of free blocks. this test takes a long time.
void
badwrite(char *s)
{
@@ -2049,9 +2072,8 @@ badwrite(char *s)
exit(0);
}
-// test whether exec() leaks memory if one of the
-// arguments is invalid. the test passes if
-// the kernel doesn't panic.
+// regression test. test whether exec() leaks memory if one of the
+// arguments is invalid. the test passes if the kernel doesn't panic.
void
badarg(char *s)
{
@@ -2102,6 +2124,7 @@ main(int argc, char *argv[])
void (*f)(char *);
char *s;
} tests[] = {
+ {reparent2, "reparent2"},
{pgbug, "pgbug" },
{sbrkbugs, "sbrkbugs" },
// {badwrite, "badwrite" },