Files

62 lines
2.1 KiB
C

#include "ulib.h"
/*
* Only ever spawned by eintrtest.c. Attaches as the READ end of its own,
* self-contained pipe (userPipeCreate/userPipeAttach) that no writer will
* ever attach to -- the exact same "blocked forever" setup killtest.c's
* killvictim.c already uses for threadKill -- but the way out here is an
* ORDINARY signal (sigTerm, default disposition Terminate) going through
* the FULL sigRaise -> pending-bit -> early-wake -> deliverPendingSignals
* pipeline (signal.h/sched.c's threadWakeForSignal), not threadKill's
* direct ThreadState bypass. Before that early-wake existed, sigRaise only
* ever set a pending bit and left a Blocked thread exactly where it was --
* delivery only happens at a return-to-ring3 this process would otherwise
* never naturally reach again, so sigTerm sent here would have done
* nothing observable, ever: the read below is never naturally satisfied,
* by construction.
*/
int main(int argc, char** argv)
{
print("eintrtarget: start, pid=");
printDec(userGetpid());
print("\n");
if (argc != 2) {
print("eintrtarget: FAIL expected one argv (ready handle)\n");
return 1;
}
long victimHandle = userPipeCreate();
if (victimHandle < 0) {
print("eintrtarget: FAIL create victim pipe\n");
return 1;
}
long victimFd = userPipeAttach(victimHandle, 0);
if (victimFd < 0) {
print("eintrtarget: FAIL attach victim pipe\n");
return 1;
}
long readyHandle = parseDec(argv[1]);
long readyFd = userPipeAttach(readyHandle, 1);
if (readyFd < 0) {
print("eintrtarget: FAIL attach ready pipe\n");
return 1;
}
if (userWrite((int)readyFd, "r", 1) != 1) {
print("eintrtarget: FAIL write ready byte\n");
return 1;
}
userClose((int)readyFd);
print("eintrtarget: blocking on read forever\n");
char buffer[4];
userRead((int)victimFd, buffer, sizeof(buffer));
/* Only reached if userRead somehow returned on its own -- eintrtest.c
never writes to the victim pipe, so that would itself be a bug. */
print("eintrtarget: FAIL read returned without being signaled\n");
return 1;
}