signal: Exit RCU read-side critical section on each pass through loop
The kill_pid_info() can potentially loop indefinitely if tasks are created and deleted sufficiently quickly, and if this happens, this function will remain in a single RCU read-side critical section indefinitely. This commit therefore exits the RCU read-side critical section on each pass through the loop. Because a race must happen to retry the loop, this should have no performance impact in the common case. Reported-by: Dave Jones <davej@redhat.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Oleg Nesterov <oleg@redhat.com> Reviewed-by: Pranith Kumar <bobby.prani@gmail.com>
This commit is contained in:
		
					parent
					
						
							
								d7e2993396
							
						
					
				
			
			
				commit
				
					
						eca1a08986
					
				
			
		
					 1 changed files with 14 additions and 16 deletions
				
			
		| 
						 | 
				
			
			@ -1331,23 +1331,21 @@ int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
 | 
			
		|||
	int error = -ESRCH;
 | 
			
		||||
	struct task_struct *p;
 | 
			
		||||
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		rcu_read_lock();
 | 
			
		||||
retry:
 | 
			
		||||
		p = pid_task(pid, PIDTYPE_PID);
 | 
			
		||||
	if (p) {
 | 
			
		||||
		if (p)
 | 
			
		||||
			error = group_send_sig_info(sig, info, p);
 | 
			
		||||
		if (unlikely(error == -ESRCH))
 | 
			
		||||
			/*
 | 
			
		||||
			 * The task was unhashed in between, try again.
 | 
			
		||||
			 * If it is dead, pid_task() will return NULL,
 | 
			
		||||
			 * if we race with de_thread() it will find the
 | 
			
		||||
			 * new leader.
 | 
			
		||||
			 */
 | 
			
		||||
			goto retry;
 | 
			
		||||
	}
 | 
			
		||||
		rcu_read_unlock();
 | 
			
		||||
 | 
			
		||||
		if (likely(!p || error != -ESRCH))
 | 
			
		||||
			return error;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * The task was unhashed in between, try again.  If it
 | 
			
		||||
		 * is dead, pid_task() will return NULL, if we race with
 | 
			
		||||
		 * de_thread() it will find the new leader.
 | 
			
		||||
		 */
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kill_proc_info(int sig, struct siginfo *info, pid_t pid)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue