• Al Viro's avatar
    alpha: deal with multiple simultaneously pending signals · 494486a1
    Al Viro authored
    Unlike the other targets, alpha sets _one_ sigframe and
    buggers off until the next syscall/interrupt, even if
    more signals are pending.  It leads to quite a few unpleasant
    inconsistencies, starting with SIGSEGV potentially arriving
    not where it should and including e.g. mess with sigsuspend();
    consider two pending signals blocked until sigsuspend()
    unblocks them.  We pick the first one; then, if we are hit
    by interrupt while in the handler, we process the second one
    as well.  If we are not, and if no syscalls had been made,
    we get out of the first handler and leave the second signal
    pending; normally sigreturn() would've picked it anyway, but
    here it starts with restoring the original mask and voila -
    the second signal is blocked again.  On everything else we
    get both delivered consistently.
    
    It's actually easy to fix; the only thing to watch out for
    is prevention of double syscall restart.  Fortunately, the
    idea I've nicked from arm fix by rmk works just fine...
    
    Testcase demonstrating the behaviour in question; on alpha
    we get one or both flags set (usually one), on everything
    else both are always set.
    	#include <signal.h>
    	#include <stdio.h>
    	int had1, had2;
    	void f1(int sig) { had1 = 1; }
    	void f2(int sig) { had2 = 1; }
    	main()
    	{
    		sigset_t set1, set2;
    		sigemptyset(&set1);
    		sigemptyset(&set2);
    		sigaddset(&set2, 1);
    		sigaddset(&set2, 2);
    		signal(1, f1);
    		signal(2, f2);
    		sigprocmask(SIG_SETMASK, &set2, NULL);
    		raise(1);
    		raise(2);
    		sigsuspend(&set1);
    		printf("had1:%d had2:%d\n", had1, had2);
    	}
    Tested-by: default avatarMichael Cree <mcree@orcon.net.nz>
    Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: default avatarMatt Turner <mattst88@gmail.com>
    494486a1
entry.S 18.6 KB