From: Jeff Dike On 2.4 hosts signals are delivered in numeric order when there are multiple pending at a given time. UML developed a subtle dependency on this ordering, which broke on 2.6 hosts and the separate process and thread signal queues. This patch eliminates that dependency. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton --- 25-akpm/arch/um/kernel/process.c | 2 +- 25-akpm/arch/um/kernel/tt/exec_kern.c | 3 +++ 25-akpm/arch/um/kernel/tt/process_kern.c | 18 +++++++++++++++++- 25-akpm/arch/um/kernel/tt/trap_user.c | 2 -- 25-akpm/arch/um/os-Linux/process.c | 4 ---- 5 files changed, 21 insertions(+), 8 deletions(-) diff -puN arch/um/kernel/process.c~uml-eliminate-signal-order-delivery-dependency arch/um/kernel/process.c --- 25/arch/um/kernel/process.c~uml-eliminate-signal-order-delivery-dependency Tue Sep 14 18:29:24 2004 +++ 25-akpm/arch/um/kernel/process.c Tue Sep 14 18:29:24 2004 @@ -70,7 +70,7 @@ void init_new_thread_signals(int altstac set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGUSR2, (__sighandler_t) sig_handler, - SA_NOMASK | flags, -1); + flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); signal(SIGHUP, SIG_IGN); init_irq_signals(altstack); diff -puN arch/um/kernel/tt/exec_kern.c~uml-eliminate-signal-order-delivery-dependency arch/um/kernel/tt/exec_kern.c --- 25/arch/um/kernel/tt/exec_kern.c~uml-eliminate-signal-order-delivery-dependency Tue Sep 14 18:29:24 2004 +++ 25-akpm/arch/um/kernel/tt/exec_kern.c Tue Sep 14 18:29:24 2004 @@ -14,6 +14,7 @@ #include "kern_util.h" #include "irq_user.h" #include "time_user.h" +#include "signal_user.h" #include "mem_user.h" #include "os.h" #include "tlb.h" @@ -53,7 +54,9 @@ void flush_thread_tt(void) current->thread.request.u.exec.pid = new_pid; unprotect_stack((unsigned long) current_thread); os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); + change_sig(SIGUSR1, 0); enable_timer(); free_page(stack); protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); diff -puN arch/um/kernel/tt/process_kern.c~uml-eliminate-signal-order-delivery-dependency arch/um/kernel/tt/process_kern.c --- 25/arch/um/kernel/tt/process_kern.c~uml-eliminate-signal-order-delivery-dependency Tue Sep 14 18:29:24 2004 +++ 25-akpm/arch/um/kernel/tt/process_kern.c Tue Sep 14 18:29:24 2004 @@ -201,6 +201,7 @@ static int new_thread_proc(void *stack) local_irq_disable(); init_new_thread_stack(stack, new_thread_handler); os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); return(0); } @@ -244,6 +245,7 @@ int fork_tramp(void *stack) init_new_thread_stack(stack, finish_fork_handler); os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); return(0); } @@ -295,19 +297,30 @@ int copy_thread_tt(int nr, unsigned long current->thread.request.op = OP_FORK; current->thread.request.u.fork.pid = new_pid; os_usr1_process(os_getpid()); - return(0); + + /* Enable the signal and then disable it to ensure that it is handled + * here, and nowhere else. + */ + change_sig(SIGUSR1, 1); + + change_sig(SIGUSR1, 0); + err = 0; + out: + return(err); } void reboot_tt(void) { current->thread.request.op = OP_REBOOT; os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); } void halt_tt(void) { current->thread.request.op = OP_HALT; os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); } void kill_off_processes_tt(void) @@ -334,6 +347,9 @@ void initial_thread_cb_tt(void (*proc)(v current->thread.request.u.cb.proc = proc; current->thread.request.u.cb.arg = arg; os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); + + change_sig(SIGUSR1, 0); } } diff -puN arch/um/kernel/tt/trap_user.c~uml-eliminate-signal-order-delivery-dependency arch/um/kernel/tt/trap_user.c --- 25/arch/um/kernel/tt/trap_user.c~uml-eliminate-signal-order-delivery-dependency Tue Sep 14 18:29:24 2004 +++ 25-akpm/arch/um/kernel/tt/trap_user.c Tue Sep 14 18:29:24 2004 @@ -37,7 +37,6 @@ void sig_handler_common_tt(int sig, void if(sig != SIGUSR2) r->syscall = -1; - change_sig(SIGUSR1, 1); info = &sig_info[sig]; if(!info->is_irq) unblock_signals(); @@ -46,7 +45,6 @@ void sig_handler_common_tt(int sig, void if(is_user){ interrupt_end(); block_signals(); - change_sig(SIGUSR1, 0); set_user_mode(NULL); } *r = save_regs; diff -puN arch/um/os-Linux/process.c~uml-eliminate-signal-order-delivery-dependency arch/um/os-Linux/process.c --- 25/arch/um/os-Linux/process.c~uml-eliminate-signal-order-delivery-dependency Tue Sep 14 18:29:24 2004 +++ 25-akpm/arch/um/os-Linux/process.c Tue Sep 14 18:29:24 2004 @@ -96,11 +96,7 @@ void os_kill_process(int pid, int reap_c void os_usr1_process(int pid) { -#ifdef __NR_tkill - syscall(__NR_tkill, pid, SIGUSR1); -#else kill(pid, SIGUSR1); -#endif } int os_getpid(void) _