From Jeff Dike's changelog: Fixed an exit on reboot by disabling all possible sources of pending signals. At least I think this is the change he speaks about. Signed-off-by: Paolo 'Blaisorblade' Giarrusso --- um-linux-2.4.27-paolo/arch/um/include/irq_user.h | 1 um-linux-2.4.27-paolo/arch/um/include/os.h | 1 um-linux-2.4.27-paolo/arch/um/include/time_user.h | 1 um-linux-2.4.27-paolo/arch/um/kernel/irq_user.c | 14 +++++++++++++ um-linux-2.4.27-paolo/arch/um/kernel/process.c | 2 - um-linux-2.4.27-paolo/arch/um/kernel/sigio_kern.c | 14 ++++++++----- um-linux-2.4.27-paolo/arch/um/kernel/skas/process_kern.c | 2 - um-linux-2.4.27-paolo/arch/um/kernel/time.c | 9 ++++++++ um-linux-2.4.27-paolo/arch/um/kernel/tt/exec_kern.c | 3 ++ um-linux-2.4.27-paolo/arch/um/kernel/tt/process_kern.c | 16 +++++++++++++++ um-linux-2.4.27-paolo/arch/um/kernel/tt/trap_user.c | 2 - um-linux-2.4.27-paolo/arch/um/main.c | 14 +++++++++++++ um-linux-2.4.27-paolo/arch/um/os-Linux/file.c | 10 +++++++++ 13 files changed, 80 insertions(+), 9 deletions(-) diff -puN arch/um/include/irq_user.h~SIG-fileHandle-changes arch/um/include/irq_user.h --- um-linux-2.4.27/arch/um/include/irq_user.h~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/include/irq_user.h 2005-04-15 11:13:08.000000000 +0200 @@ -14,6 +14,7 @@ extern void free_irq_by_irq_and_dev(int extern void free_irq_by_fd(int fd); extern void reactivate_fd(int fd, int irqnum); extern void deactivate_fd(int fd, int irqnum); +extern int deactivate_all_fds(void); extern void forward_interrupts(int pid); extern void init_irq_signals(int on_sigstack); extern void forward_ipi(int fd, int pid); diff -puN arch/um/include/os.h~SIG-fileHandle-changes arch/um/include/os.h --- um-linux-2.4.27/arch/um/include/os.h~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/include/os.h 2005-04-15 11:13:08.000000000 +0200 @@ -140,6 +140,7 @@ extern int os_file_size(char *file, long extern int os_file_modtime(char *file, unsigned long *modtime); extern int os_pipe(int *fd, int stream, int close_on_exec); extern int os_set_fd_async(int fd, int owner); +extern int os_clear_fd_async(int fd); extern int os_set_fd_block(int fd, int blocking); extern int os_accept_connection(int fd); extern int os_create_unix_socket(char *file, int len, int close_on_exec); diff -puN arch/um/include/time_user.h~SIG-fileHandle-changes arch/um/include/time_user.h --- um-linux-2.4.27/arch/um/include/time_user.h~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/include/time_user.h 2005-04-15 11:13:08.000000000 +0200 @@ -11,6 +11,7 @@ extern void switch_timers(int to_real); extern void set_interval(int timer_type); extern void idle_sleep(int secs); extern void enable_timer(void); +extern void disable_timer(void); extern unsigned long time_lock(void); extern void time_unlock(unsigned long); diff -puN arch/um/kernel/irq_user.c~SIG-fileHandle-changes arch/um/kernel/irq_user.c --- um-linux-2.4.27/arch/um/kernel/irq_user.c~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/kernel/irq_user.c 2005-04-15 11:13:08.000000000 +0200 @@ -364,6 +364,20 @@ void deactivate_fd(int fd, int irqnum) irq_unlock(flags); } +int deactivate_all_fds(void) +{ + struct irq_fd *irq; + int err; + + for(irq=active_fds;irq != NULL;irq = irq->next){ + err = os_clear_fd_async(irq->fd); + if(err) + return(err); + } + + return(0); +} + void forward_ipi(int fd, int pid) { int err; diff -puN arch/um/kernel/process.c~SIG-fileHandle-changes arch/um/kernel/process.c --- um-linux-2.4.27/arch/um/kernel/process.c~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/kernel/process.c 2005-04-15 11:13:08.000000000 +0200 @@ -74,7 +74,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/sigio_kern.c~SIG-fileHandle-changes arch/um/kernel/sigio_kern.c --- um-linux-2.4.27/arch/um/kernel/sigio_kern.c~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/kernel/sigio_kern.c 2005-04-15 11:13:08.000000000 +0200 @@ -15,7 +15,7 @@ /* Protected by sigio_lock() called from write_sigio_workaround */ static int sigio_irq_fd = -1; -void sigio_interrupt(int irq, void *data, struct pt_regs *unused) +static void sigio_interrupt(int irq, void *data, struct pt_regs *unused) { read_sigio_fd(sigio_irq_fd); reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); @@ -23,10 +23,14 @@ void sigio_interrupt(int irq, void *data int write_sigio_irq(int fd) { - if(um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, - SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio", - NULL)){ - printk("write_sigio_irq : um_request_irq failed\n"); + int err; + + err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, + SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio", + NULL); + if(err){ + printk("write_sigio_irq : um_request_irq failed, err = %d\n", + err); return(-1); } sigio_irq_fd = fd; diff -puN arch/um/kernel/skas/process_kern.c~SIG-fileHandle-changes arch/um/kernel/skas/process_kern.c --- um-linux-2.4.27/arch/um/kernel/skas/process_kern.c~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/kernel/skas/process_kern.c 2005-04-15 11:13:08.000000000 +0200 @@ -160,9 +160,9 @@ int start_uml_skas(void) { start_userspace(0); capture_signal_stack(); - idle_timer(); init_new_thread_signals(1); + idle_timer(); init_task.thread.request.u.thread.proc = start_kernel_proc; init_task.thread.request.u.thread.arg = NULL; diff -puN arch/um/kernel/time.c~SIG-fileHandle-changes arch/um/kernel/time.c --- um-linux-2.4.27/arch/um/kernel/time.c~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/kernel/time.c 2005-04-15 11:13:08.000000000 +0200 @@ -47,6 +47,15 @@ void enable_timer(void) errno); } +void disable_timer(void) +{ + struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); + if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || + (setitimer(ITIMER_REAL, &disable, NULL) < 0)) + printk("disnable_timer - setitimer failed, errno = %d\n", + errno); +} + void switch_timers(int to_real) { struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); diff -puN arch/um/kernel/tt/exec_kern.c~SIG-fileHandle-changes arch/um/kernel/tt/exec_kern.c --- um-linux-2.4.27/arch/um/kernel/tt/exec_kern.c~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/kernel/tt/exec_kern.c 2005-04-15 11:13:08.000000000 +0200 @@ -14,6 +14,7 @@ #include "irq_user.h" #include "time_user.h" #include "mem_user.h" +#include "signal_user.h" #include "os.h" #include "tlb.h" #include "mode.h" @@ -52,7 +53,9 @@ void flush_thread_tt(void) current->thread.request.u.exec.pid = new_pid; unprotect_stack((unsigned long) current); 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~SIG-fileHandle-changes arch/um/kernel/tt/process_kern.c --- um-linux-2.4.27/arch/um/kernel/tt/process_kern.c~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/kernel/tt/process_kern.c 2005-04-15 11:13:08.000000000 +0200 @@ -153,6 +153,12 @@ static void new_thread_handler(int sig) sti(); 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) @@ -173,6 +179,7 @@ static int new_thread_proc(void *stack) cli(); init_new_thread_stack(stack, new_thread_handler); os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); return(0); } @@ -215,6 +222,7 @@ int fork_tramp(void *stack) arch_init_thread(); init_new_thread_stack(stack, finish_fork_handler); os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); return(0); } @@ -266,6 +274,9 @@ 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()); + change_sig(SIGUSR1, 1); + + change_sig(SIGUSR1, 0); return(0); } @@ -273,12 +284,14 @@ 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) @@ -307,6 +320,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~SIG-fileHandle-changes arch/um/kernel/tt/trap_user.c --- um-linux-2.4.27/arch/um/kernel/tt/trap_user.c~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/kernel/tt/trap_user.c 2005-04-15 11:13:08.000000000 +0200 @@ -30,7 +30,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(); @@ -39,7 +38,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/main.c~SIG-fileHandle-changes arch/um/main.c --- um-linux-2.4.27/arch/um/main.c~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/main.c 2005-04-15 11:13:08.000000000 +0200 @@ -17,6 +17,8 @@ #include "kern_util.h" #include "mem_user.h" #include "signal_user.h" +#include "time_user.h" +#include "irq_user.h" #include "user.h" #include "init.h" #include "mode.h" @@ -147,8 +149,20 @@ int main(int argc, char **argv, char **e /* Reboot */ if(ret){ + int err; + printf("\n"); + /* Let any pending signals fire, then disable them. This + * ensures that they won't be delivered after the exec, when + * they are definitely not expected. + */ + unblock_signals(); + disable_timer(); + err = deactivate_all_fds(); + if(err) + printf("deactivate_all_fds failed, errno = %d\n", -err); + execvp(new_argv[0], new_argv); perror("Failed to exec kernel"); ret = 1; diff -puN arch/um/os-Linux/file.c~SIG-fileHandle-changes arch/um/os-Linux/file.c --- um-linux-2.4.27/arch/um/os-Linux/file.c~SIG-fileHandle-changes 2005-04-15 11:13:08.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/os-Linux/file.c 2005-04-15 11:13:08.000000000 +0200 @@ -495,6 +495,16 @@ int os_set_fd_async(int fd, int owner) return(0); } +int os_clear_fd_async(int fd) +{ + int flags = fcntl(fd, F_GETFL); + + flags &= ~(O_ASYNC | O_NONBLOCK); + if(fcntl(fd, F_SETFL, flags) < 0) + return(-errno); + return(0); +} + int os_set_fd_block(int fd, int blocking) { int flags; _