feat: add onUsr1, streq and printOut
This commit is contained in:
1 parent
35e5dad2f3
commit
2709025a74
4 files changed
+201
No files matched your search
@@ -0,0 +1,95 @@
|
||||
#include "ulib.h"
|
||||
|
||||
/*
|
||||
* Only ever spawned by sigtest.c, with a shared pipe handle as argv[1]
|
||||
* (decToString'd, exactly like fifomaster.c's children -- see that file).
|
||||
* Proves real, catchable signal delivery end to end: install a handler for
|
||||
* sigUsr1 through userSigAction, wait to actually be interrupted by one
|
||||
* arriving from a completely separate process (sigtest.c, via
|
||||
* userSigSend -- not the kernel injecting it directly), and keep running
|
||||
* normally afterwards -- the handler firing AND the loop below correctly
|
||||
* resuming (not corrupting registers, not re-entering main, not looping
|
||||
* forever) is the round trip through signal.c's sigConsumePending, the
|
||||
* shared trampoline page (sigTrampoline.S), and sysSigReturn all actually
|
||||
* working together, not just each piece compiling.
|
||||
*
|
||||
* The pipe exists purely to close a real race sigtest.c originally papered
|
||||
* over with a fixed userSleep: sigUsr1's default disposition (no handler
|
||||
* installed) is Terminate, not Ignore, so a signal that arrives before
|
||||
* userSigAction below has actually run would kill this process instead of
|
||||
* being caught -- observed for real under host load (sigtarget killed by
|
||||
* "uncaught signal 10" before it ever printed "waiting for signal").
|
||||
* Writing one byte AFTER installing the handler, and having sigtest.c
|
||||
* block on reading it before ever calling userSigSend, makes "handler
|
||||
* installed" happen-before "signal sent" for real, the same guarantee
|
||||
* fifomaster.c's children get from their own shared pipe.
|
||||
*/
|
||||
|
||||
static volatile int handlerFired = 0;
|
||||
static volatile int handlerSignum = 0;
|
||||
|
||||
static void onUsr1(int signum)
|
||||
{
|
||||
handlerFired = 1;
|
||||
handlerSignum = signum;
|
||||
print("sigtarget: handler invoked signum=");
|
||||
printDec(signum);
|
||||
print("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
print("sigtarget: start, pid=");
|
||||
printDec(userGetpid());
|
||||
print("\n");
|
||||
|
||||
if (argc != 2) {
|
||||
print("sigtarget: FAIL expected one argv (pipe handle)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (userSigAction(sigUsr1, onUsr1, 0, 0) == (long)sigSetFailed) {
|
||||
print("sigtarget: FAIL install handler\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
long handle = parseDec(argv[1]);
|
||||
long readyFd = userPipeAttach(handle, 1);
|
||||
if (readyFd < 0) {
|
||||
print("sigtarget: FAIL attach ready pipe\n");
|
||||
return 1;
|
||||
}
|
||||
if (userWrite((int)readyFd, "r", 1) != 1) {
|
||||
print("sigtarget: FAIL write ready byte\n");
|
||||
return 1;
|
||||
}
|
||||
userClose((int)readyFd);
|
||||
|
||||
print("sigtarget: waiting for signal\n");
|
||||
|
||||
/* Several short sleeps rather than one long one: this kernel only
|
||||
checks for a pending signal when the target thread actually returns
|
||||
to ring 3 (isr.c's deliverPendingSignals) -- a thread that is still
|
||||
genuinely Sleeping is not scheduled at all, so a shorter sleep gives
|
||||
sigtest.c's userSigSend more chances to land promptly, without
|
||||
depending on exact timing between the two independent processes. */
|
||||
for (int i = 0; i < 40 && !handlerFired; i++)
|
||||
userSleep(20);
|
||||
|
||||
if (!handlerFired) {
|
||||
print("sigtarget: FAIL handler never fired\n");
|
||||
return 1;
|
||||
}
|
||||
if (handlerSignum != sigUsr1) {
|
||||
print("sigtarget: FAIL wrong signum delivered\n");
|
||||
return 1;
|
||||
}
|
||||
print("sigtarget: handler-fired-ok\n");
|
||||
|
||||
/* Reached only if sysSigReturn correctly restored the exact
|
||||
pre-signal context: a corrupted resume (wrong rip/rsp/registers)
|
||||
would have crashed, hung, or skipped straight past this line
|
||||
instead of returning here from the interrupted sleep loop above. */
|
||||
print("sigtarget: resumed-after-handler-ok\n");
|
||||
return 42;
|
||||
}
|
||||
Reference in new issue
Block a user