linux-stable-rt/arch/alpha/kernel
Al Viro 494486a1d2 alpha: deal with multiple simultaneously pending signals
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: Michael Cree <mcree@orcon.net.nz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Matt Turner <mattst88@gmail.com>
2010-09-18 23:08:29 -04:00
..
.gitignore
Makefile
alpha_ksyms.c
asm-offsets.c
binfmt_loader.c
console.c
core_apecs.c
core_cia.c
core_irongate.c
core_lca.c
core_marvel.c
core_mcpcia.c
core_polaris.c
core_t2.c
core_titan.c
core_tsunami.c
core_wildfire.c
entry.S alpha: deal with multiple simultaneously pending signals 2010-09-18 23:08:29 -04:00
err_common.c
err_ev6.c alpha: Use static const char * const where possible 2010-09-18 23:06:17 -04:00
err_ev7.c
err_impl.h
err_marvel.c alpha: Use static const char * const where possible 2010-09-18 23:06:17 -04:00
err_titan.c alpha: Use static const char * const where possible 2010-09-18 23:06:17 -04:00
es1888.c
gct.c
head.S
init_task.c
io.c
irq.c
irq_alpha.c
irq_i8259.c
irq_impl.h
irq_pyxis.c
irq_srm.c
machvec_impl.h
module.c
osf_sys.c alpha: kill big kernel lock 2010-09-18 23:06:18 -04:00
pc873xx.c
pc873xx.h
pci-noop.c
pci-sysfs.c alpha: remove unnecessary cast from void* in assignment. 2010-09-18 23:06:17 -04:00
pci.c
pci_impl.h
pci_iommu.c
perf_event.c alpha: convert perf_event to use local_t 2010-08-31 22:46:04 -04:00
process.c Make do_execve() take a const filename pointer 2010-08-17 18:07:43 -07:00
proto.h Fix call to replaced SuperIO functions 2010-08-31 22:45:31 -04:00
ptrace.c
setup.c
signal.c alpha: unb0rk sigsuspend() and rt_sigsuspend() 2010-09-18 23:08:28 -04:00
smc37c93x.c
smc37c669.c
smp.c
srm_env.c alpha: remove unnecessary cast from void* in assignment. 2010-09-18 23:06:17 -04:00
srmcons.c
sys_alcor.c
sys_cabriolet.c Fix call to replaced SuperIO functions 2010-08-31 22:45:31 -04:00
sys_dp264.c
sys_eb64p.c
sys_eiger.c
sys_jensen.c
sys_marvel.c
sys_miata.c
sys_mikasa.c
sys_nautilus.c
sys_noritake.c
sys_rawhide.c
sys_ruffian.c
sys_rx164.c
sys_sable.c
sys_sio.c
sys_sx164.c
sys_takara.c Fix call to replaced SuperIO functions 2010-08-31 22:45:31 -04:00
sys_titan.c
sys_wildfire.c
systbls.S alpha: wire up fanotify and prlimit64 syscalls 2010-09-18 23:06:19 -04:00
time.c alpha: Shift perf event pending work earlier in timer interrupt 2010-09-18 23:06:19 -04:00
traps.c alpha: kill big kernel lock 2010-09-18 23:06:18 -04:00
vmlinux.lds.S