# This patch changes UML's internal signal handling so that it is not dependent # on the host delivering signals in a particular order, i.e. in numeric order. # This was prompted by 2.6 changes which involve signals being queued onto # two queues, a process queue and a task queue. Signals are picked off one, # and then off the other, and when there are signals on both, they may be # delivered in the opposite order that they were on 2.4 hosts. There was # an implicit assumption in UML that SIGUSR1 would be delivered before anything # else, which was true for a while because its signal number is lower than any # of the others that it cares about. Index: um/arch/um/kernel/tt/exec_kern.c =================================================================== --- um.orig/arch/um/kernel/tt/exec_kern.c 2004-08-06 16:25:45.000000000 -0400 +++ um/arch/um/kernel/tt/exec_kern.c 2004-08-06 16:29:46.000000000 -0400 @@ -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" @@ -54,7 +55,9 @@ 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); Index: um/arch/um/kernel/tt/process_kern.c =================================================================== --- um.orig/arch/um/kernel/tt/process_kern.c 2004-08-06 16:25:45.000000000 -0400 +++ um/arch/um/kernel/tt/process_kern.c 2004-08-06 16:29:46.000000000 -0400 @@ -161,6 +161,12 @@ local_irq_enable(); if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) do_exit(0); + + /* XXX No set_user_mode here because a newly execed process will + * immediately segfault on its non-existent IP, coming straight back + * to the signal handler, which will call set_user_mode on its way + * out. This should probably change since it's confusing. + */ } static int new_thread_proc(void *stack) @@ -183,6 +189,7 @@ local_irq_disable(); init_new_thread_stack(stack, new_thread_handler); os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); return(0); } @@ -226,6 +233,7 @@ init_new_thread_stack(stack, finish_fork_handler); os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); return(0); } @@ -278,6 +286,13 @@ current->thread.request.op = OP_FORK; current->thread.request.u.fork.pid = new_pid; os_usr1_process(os_getpid()); + + /* 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); @@ -287,12 +302,14 @@ { 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) @@ -319,6 +336,9 @@ 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); } } Index: um/arch/um/kernel/tt/trap_user.c =================================================================== --- um.orig/arch/um/kernel/tt/trap_user.c 2004-08-06 16:25:45.000000000 -0400 +++ um/arch/um/kernel/tt/trap_user.c 2004-08-06 16:29:46.000000000 -0400 @@ -37,7 +37,6 @@ if(sig != SIGUSR2) r->syscall = -1; - change_sig(SIGUSR1, 1); info = &sig_info[sig]; if(!info->is_irq) unblock_signals(); @@ -46,7 +45,6 @@ if(is_user){ interrupt_end(); block_signals(); - change_sig(SIGUSR1, 0); set_user_mode(NULL); } *r = save_regs;