示例#1
0
/**
 * @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);
	}
}
示例#2
0
文件: signal.c 项目: Theldus/nanvix
/**
 * @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);
}