Files

81 lines
2.8 KiB
C

#include "ulib.h"
/*
* Companion to jobctlfg.c: loaded the same way, on demand, when kmain.c's
* jobctlDriverThread types "jobctlbg &" at the real interactive shell.
* The trailing "&" (shell.c's runProgram) routes this through
* jobctlRunBackground (jobctl.c) instead of jobctlSpawnForeground -- own
* new process group leader exactly like jobctlfg.c, but the shell never
* calls keyboardSetForegroundPgid for it and never blocks waiting for it
* either, a real shell's `&` job semantics. This is the CONTROL side of
* the jobctlfg/jobctlbg pair: jobctlfg proves the shell's foreground
* grant actually reaches an injected Ctrl-C; this file proves that exact
* same event does NOT reach a job the shell deliberately left in the
* background -- if shell.c's `&` handling or jobctl.c's group-leader
* assignment were ever broken such that this process shared jobctlfg's
* group (or somehow ended up foreground itself), this process would
* already be Dead by the time jobctlDriverThread later tries to prove it
* alive, and its own needles below would simply never appear.
*
* Also exercises the actual sysGetpgid syscall boundary (unreachable from
* KTEST, which runs before schedStart() with no int 0x80 path at all) to
* confirm jobctl.c's threadSetPgid(pid, pid) call genuinely took effect
* from ring3's own point of view, not just internally.
*/
static volatile int handlerFired = 0;
static void onUsr1(int signum)
{
(void)signum;
handlerFired = 1;
print("jobctlbg: still-alive-after-ctrlc-ok\n");
}
int main(void)
{
long myPid = userGetpid();
print("jobctlbg: start, pid=");
printDec(myPid);
print("\n");
long pgid = userGetpgid(0);
if (pgid != myPid) {
print("jobctlbg: FAIL expected to be its own group leader\n");
return 1;
}
print("jobctlbg: own-process-group-ok\n");
if (userSigAction(sigUsr1, onUsr1, 0, 0) == (long)sigSetFailed) {
print("jobctlbg: FAIL install handler\n");
return 1;
}
long victimHandle = userPipeCreate();
if (victimHandle < 0) {
print("jobctlbg: FAIL create victim pipe\n");
return 1;
}
long victimFd = userPipeAttach(victimHandle, 0);
if (victimFd < 0) {
print("jobctlbg: FAIL attach victim pipe\n");
return 1;
}
print("jobctlbg: ready, blocking on go pipe\n");
char buffer[4];
userRead((int)victimFd, buffer, sizeof(buffer));
if (!handlerFired) {
print("jobctlbg: FAIL read returned without being signaled\n");
return 1;
}
/* Reached only if the read was genuinely interrupted (errInterrupted,
no sigFlagRestart) by onUsr1 above, sent by kmain.c's own driver
thread well AFTER the Ctrl-C injected for jobctlfg -- proving this
backgrounded process was never touched by it. */
print("jobctlbg: resumed-after-signal-ok\n");
return 0;
}