diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index d0f97127adf691a651d86f896760e5cf5fe01a4e..025d3be8aca4ae522e40b6aaa2a8623834805243 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -462,12 +462,15 @@ int line_open(struct line *lines, struct tty_struct *tty, return err; } +static void unregister_winch(struct tty_struct *tty); + void line_close(struct tty_struct *tty, struct file * filp) { struct line *line = tty->driver_data; - /* XXX: I assume this should be called in process context, not with interrupt - * disabled!*/ + /* XXX: I assume this should be called in process context, not with + * interrupts disabled! + */ spin_lock_irq(&line->lock); /* We ignore the error anyway! */ @@ -478,6 +481,12 @@ void line_close(struct tty_struct *tty, struct file * filp) line_disable(tty, -1); tty->driver_data = NULL; } + + if((line->count == 0) && line->sigio){ + unregister_winch(tty); + line->sigio = 0; + } + spin_unlock_irq(&line->lock); } @@ -729,6 +738,34 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) up(&winch_handler_sem); } +static void unregister_winch(struct tty_struct *tty) +{ + struct list_head *ele; + struct winch *winch, *found = NULL; + + down(&winch_handler_sem); + list_for_each(ele, &winch_handlers){ + winch = list_entry(ele, struct winch, list); + if(winch->tty == tty){ + found = winch; + break; + } + } + + if(found == NULL) + goto out; + + if(winch->pid != -1) + os_kill_process(winch->pid, 1); + + free_irq_by_irq_and_dev(WINCH_IRQ, winch); + free_irq(WINCH_IRQ, winch); + list_del(&winch->list); + kfree(winch); + out: + up(&winch_handler_sem); +} + static void winch_cleanup(void) { struct list_head *ele; diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 07340c8cf20305c5a2985f8d93915f213e7f5f03..d246d5a24609e3657649cc0793b15233c63392db 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -160,6 +160,7 @@ extern void os_kill_process(int pid, int reap_child); extern void os_kill_ptraced_process(int pid, int reap_child); extern void os_usr1_process(int pid); extern int os_getpid(void); +extern int os_getpgrp(void); extern int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, int r, int w, int x); diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index d71e8f00810feaab0731ae30cc3aeb8bd3b66959..d44fb52825479fb8c00f67360c547c37473e1877 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -163,7 +163,6 @@ void __init init_IRQ(void) irq_desc[i].handler = &SIGIO_irq_type; enable_irq(i); } - init_irq_signals(0); } /* diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index f76a2692adcae42ddc1ffcef5ce822027a44f320..51f8e5a8ac6a9d60357888e56462f18f6b2ff93e 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -65,8 +65,6 @@ void init_new_thread_signals(int altstack) SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); - set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGUSR2, (__sighandler_t) sig_handler, flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); signal(SIGHUP, SIG_IGN); diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index 668df13d8c9d67e25ceeaaf908fca11e18c58808..e89218958f38c4bbe9bd1473363a862235ad4fcd 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -182,6 +182,7 @@ static int write_sigio_thread(void *unused) int i, n, respond_fd; char c; + signal(SIGWINCH, SIG_IGN); fds = ¤t_poll; while(1){ n = poll(fds->poll, fds->used, -1); diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index c0b30515dfb6fe70d8bfd3ed65d5a1b6b57af92f..4dc13bc8cfd8faf87d499f2a9dfca050327905c6 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -28,10 +28,11 @@ #include "chan_user.h" #include "signal_user.h" #include "registers.h" +#include "process.h" int is_skas_winch(int pid, int fd, void *data) { - if(pid != os_getpid()) + if(pid != os_getpgrp()) return(0); register_winch_irq(-1, fd, -1, data); @@ -259,6 +260,10 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) sigjmp_buf **switch_buf = switch_buf_ptr; int n; + set_handler(SIGWINCH, (__sighandler_t) sig_handler, + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, + SIGVTALRM, -1); + *fork_buf_ptr = &initial_jmpbuf; n = sigsetjmp(initial_jmpbuf, 1); if(n == 0) diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index f7b1753a025c9a15bae6ccc0a41e6af16f1d7046..d11e7399d7a1a894097ec0b0a45360803eae10b5 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c @@ -26,6 +26,7 @@ #include "kern_util.h" #include "chan_user.h" #include "ptrace_user.h" +#include "irq_user.h" #include "mode.h" #include "tt.h" @@ -33,7 +34,7 @@ static int tracer_winch[2]; int is_tracer_winch(int pid, int fd, void *data) { - if(pid != tracing_pid) + if(pid != os_getpgrp()) return(0); register_winch_irq(tracer_winch[0], fd, -1, data); @@ -119,6 +120,7 @@ static int signal_tramp(void *arg) signal(SIGSEGV, (__sighandler_t) sig_handler); set_cmdline("(idle thread)"); set_init_pid(os_getpid()); + init_irq_signals(0); proc = arg; return((*proc)(NULL)); } diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index ba9ca1cc790a52d6f7940fc9515d77e471f39328..1e126bfd31a7b89b5d9663ae4a1b7cefcb294422 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -123,6 +123,11 @@ int os_getpid(void) return(getpid()); } +int os_getpgrp(void) +{ + return getpgrp(); +} + int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, int r, int w, int x) {