mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	signal: add block_sigmask() for adding sigmask to current->blocked
Abstract the code sequence for adding a signal handler's sa_mask to current->blocked because the sequence is identical for all architectures. Furthermore, in the past some architectures actually got this code wrong, so introduce a wrapper that all architectures can use. Signed-off-by: Matt Fleming <matt.fleming@intel.com> Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@elte.hu> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Tejun Heo <tj@kernel.org> Cc: "David S. Miller" <davem@davemloft.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									f350b1778f
								
							
						
					
					
						commit
						5e6292c0f2
					
				
					 3 changed files with 23 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -682,7 +682,6 @@ static int
 | 
			
		|||
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 | 
			
		||||
		struct pt_regs *regs)
 | 
			
		||||
{
 | 
			
		||||
	sigset_t blocked;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	/* Are we from a system call? */
 | 
			
		||||
| 
						 | 
				
			
			@ -733,10 +732,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 | 
			
		|||
	 */
 | 
			
		||||
	regs->flags &= ~X86_EFLAGS_TF;
 | 
			
		||||
 | 
			
		||||
	sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask);
 | 
			
		||||
	if (!(ka->sa.sa_flags & SA_NODEFER))
 | 
			
		||||
		sigaddset(&blocked, sig);
 | 
			
		||||
	set_current_blocked(&blocked);
 | 
			
		||||
	block_sigmask(ka, sig);
 | 
			
		||||
 | 
			
		||||
	tracehook_signal_handler(sig, info, ka, regs,
 | 
			
		||||
				 test_thread_flag(TIF_SINGLESTEP));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -254,6 +254,7 @@ extern void set_current_blocked(const sigset_t *);
 | 
			
		|||
extern int show_unhandled_signals;
 | 
			
		||||
 | 
			
		||||
extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
 | 
			
		||||
extern void block_sigmask(struct k_sigaction *ka, int signr);
 | 
			
		||||
extern void exit_signals(struct task_struct *tsk);
 | 
			
		||||
 | 
			
		||||
extern struct kmem_cache *sighand_cachep;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2318,6 +2318,27 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
 | 
			
		|||
	return signr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * block_sigmask - add @ka's signal mask to current->blocked
 | 
			
		||||
 * @ka: action for @signr
 | 
			
		||||
 * @signr: signal that has been successfully delivered
 | 
			
		||||
 *
 | 
			
		||||
 * This function should be called when a signal has succesfully been
 | 
			
		||||
 * delivered. It adds the mask of signals for @ka to current->blocked
 | 
			
		||||
 * so that they are blocked during the execution of the signal
 | 
			
		||||
 * handler. In addition, @signr will be blocked unless %SA_NODEFER is
 | 
			
		||||
 * set in @ka->sa.sa_flags.
 | 
			
		||||
 */
 | 
			
		||||
void block_sigmask(struct k_sigaction *ka, int signr)
 | 
			
		||||
{
 | 
			
		||||
	sigset_t blocked;
 | 
			
		||||
 | 
			
		||||
	sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask);
 | 
			
		||||
	if (!(ka->sa.sa_flags & SA_NODEFER))
 | 
			
		||||
		sigaddset(&blocked, signr);
 | 
			
		||||
	set_current_blocked(&blocked);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * It could be that complete_signal() picked us to notify about the
 | 
			
		||||
 * group-wide signal. Other threads should be notified now to take
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue