Files

69 lines
2.1 KiB
C

#include "ulib.h"
/*
* Exercises threadKill (sched.c) end to end through sysKill: spawns
* killvictim.c (which blocks forever in a real, syscall-level pipe read
* with no writer ever attaching), waits long enough for it to actually
* reach and park inside that read, then kills it and confirms userWait
* reports exactly the killed exit status (9) -- the only way this kernel
* can ever recover a process stuck in a genuine block, now that
* sysRead/sysWrite can really block (pipe.h/vfs.h, same wave as this).
*/
int main(void)
{
print("killtest: start, pid=");
printDec(userGetpid());
print("\n");
if (userKill(userGetpid()) != -1) {
print("killtest: FAIL self-kill should be rejected\n");
return 1;
}
print("killtest: self-kill rejected\n");
if (userKill(999999) != -1) {
print("killtest: FAIL kill of bogus pid should fail\n");
return 1;
}
print("killtest: kill bad pid rejected\n");
long victim = userSpawn("/bin/killvictim", 0);
if (victim < 0) {
print("killtest: FAIL spawn killvictim\n");
return 1;
}
/* Give the victim time to actually attach and reach its blocking read
-- killing it before it ever calls userRead would still "work" (any
Runnable/Sleeping/Blocked thread is a valid target), but would not
prove the interesting case: tearing down a call already parked
mid-syscall. */
userSleep(100);
if (userKill(victim) != 0) {
print("killtest: FAIL kill victim\n");
return 1;
}
print("killtest: killed victim\n");
long status = userWait(victim);
print("killtest: victim exit status=");
printDec(status);
print("\n");
if (status != 9) {
print("killtest: FAIL expected exit status 9\n");
return 1;
}
/* Already dead and reaped (userWait above reaped it): killing it again
must fail cleanly, not resurrect a slot that has since been reused. */
if (userKill(victim) != -1) {
print("killtest: FAIL kill of already-reaped pid should fail\n");
return 1;
}
print("killtest: kill-ok\n");
return 0;
}