/** * @brief Sends a signal to a process. * * @param proc Process to send the signal. * @param sig Signal to be sent. */ PUBLIC void sndsig(struct process *proc, int sig) { /* Ignore this. */ if (IGNORING(proc, sig) && (sig != SIGCHLD)) return; /* Set signal flag. */ proc->received |= (1 << sig); /* * SIGCONT is somewhat special. The receiving process * is resumed even if SIGCONT is being ignored, * otherwise it could stop forever. */ if (sig == SIGCONT) { resume(proc); /* * The process is not catching SIGCONT and the * default action for this signal has just been * taken. */ if (!CATCHING(proc, sig)) { proc->received &= ~(1 << sig); return; } } /* Wake up process. */ if (proc->state == PROC_WAITING) { if (proc == *proc->chain) *proc->chain = proc->next; else { struct process *p; for (p = *proc->chain; p->next != proc; p = p->next) noop() ; p->next = proc->next; } sched(proc); } }
/** * @brief Checks if the current process has a pending signal. * * @returns The number of the signal that is pending. If no signal is pending, * SIGNULL is returned. */ PUBLIC int issig(void) { int ret; ret = SIGNULL; /* Find a pending signal that is not being ignored. */ for (int i = 1; i < NR_SIGNALS; i++) { /* Skip. */ if (!(curr_proc->received & (1 << i))) continue; /* * Default action for SIGCONT has already been taken. If the current * process is not catching SIGCONT, we have to clear the signal flag. */ if (i == SIGCONT) { if (CATCHING(curr_proc, i)) return (SIGCONT); ret = SIGCONT; curr_proc->received &= ~(1 << i); } /* * SIGCHLD is somewhat special. If the current process * has set SIG_IGN to handle SIGCHLD, the child processes * should not become zombie processes. However, if * the current process is catching SIGCHLD or handling it * with the default handler (SIG_DFL), child processes do * become zombie processes and they are buried in wait(). */ else if (i == SIGCHLD) { /* The current process has set SIG_IGN to handle SIGCHLD. */ if (curr_proc->handlers[SIGCHLD] == SIG_IGN) { curr_proc->received &= ~(1 << i); /* Bury zombie child processes. */ for (struct process *p = FIRST_PROC; p <= LAST_PROC; p++) { if ((p->father == curr_proc) && (p->state==PROC_ZOMBIE)) bury(p); } /* * The current process still have child processes, * so try to find another signal that is pending * and not being ignored. */ if (curr_proc->nchildren) continue; return (SIGNULL); } /* * Clear the signal flag for SIGCHLD since the current * process is not catching this signal and the default * action is to ignore it. */ else if (curr_proc->handlers[SIGCHLD] == SIG_DFL) { curr_proc->received &= ~(1 << i); return (SIGNULL); } return (SIGCHLD); } /* * Check if the default action for this signal * is to stop execution. If so, we do it now. */ if (curr_proc->handlers[i] == SIG_DFL) { if (sigdfl[i] == (sighandler_t)&stop) { curr_proc->received &= ~(1 << i); stop(); return (SIGNULL); } } return (i); } return (ret); }