diff options
author | Jeff Dike <jdike@addtoit.com> | 2005-05-05 19:15:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-05-05 19:36:36 -0400 |
commit | cd2ee4a30cc0775d8b54e5b958613361a7cacfec (patch) | |
tree | edea72ea7d723a1c35675632850916d77084581b /arch | |
parent | c578455a3eccf4dd7bd111e77129c301d6d67914 (diff) |
[PATCH] uml: Fix SIGWINCH relaying
This makes SIGWINCH work again, and fixes a couple of SIGWINCH-associated
crashes. First, the sigio thread disables SIGWINCH because all hell breaks
loose if it ever gets one and tries to call the signal handling code. Second,
there was a problem with deferencing tty structs after they were freed. The
SIGWINCH support for a tty wasn't being turned off or freed after the tty went
away.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/um/drivers/line.c | 41 | ||||
-rw-r--r-- | arch/um/include/os.h | 1 | ||||
-rw-r--r-- | arch/um/kernel/irq.c | 1 | ||||
-rw-r--r-- | arch/um/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/um/kernel/sigio_user.c | 1 | ||||
-rw-r--r-- | arch/um/kernel/skas/process.c | 7 | ||||
-rw-r--r-- | arch/um/kernel/tt/tracer.c | 4 | ||||
-rw-r--r-- | arch/um/os-Linux/process.c | 5 |
8 files changed, 55 insertions, 7 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index d0f97127adf6..025d3be8aca4 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -462,12 +462,15 @@ out: | |||
462 | return err; | 462 | return err; |
463 | } | 463 | } |
464 | 464 | ||
465 | static void unregister_winch(struct tty_struct *tty); | ||
466 | |||
465 | void line_close(struct tty_struct *tty, struct file * filp) | 467 | void line_close(struct tty_struct *tty, struct file * filp) |
466 | { | 468 | { |
467 | struct line *line = tty->driver_data; | 469 | struct line *line = tty->driver_data; |
468 | 470 | ||
469 | /* XXX: I assume this should be called in process context, not with interrupt | 471 | /* XXX: I assume this should be called in process context, not with |
470 | * disabled!*/ | 472 | * interrupts disabled! |
473 | */ | ||
471 | spin_lock_irq(&line->lock); | 474 | spin_lock_irq(&line->lock); |
472 | 475 | ||
473 | /* We ignore the error anyway! */ | 476 | /* We ignore the error anyway! */ |
@@ -478,6 +481,12 @@ void line_close(struct tty_struct *tty, struct file * filp) | |||
478 | line_disable(tty, -1); | 481 | line_disable(tty, -1); |
479 | tty->driver_data = NULL; | 482 | tty->driver_data = NULL; |
480 | } | 483 | } |
484 | |||
485 | if((line->count == 0) && line->sigio){ | ||
486 | unregister_winch(tty); | ||
487 | line->sigio = 0; | ||
488 | } | ||
489 | |||
481 | spin_unlock_irq(&line->lock); | 490 | spin_unlock_irq(&line->lock); |
482 | } | 491 | } |
483 | 492 | ||
@@ -729,6 +738,34 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) | |||
729 | up(&winch_handler_sem); | 738 | up(&winch_handler_sem); |
730 | } | 739 | } |
731 | 740 | ||
741 | static void unregister_winch(struct tty_struct *tty) | ||
742 | { | ||
743 | struct list_head *ele; | ||
744 | struct winch *winch, *found = NULL; | ||
745 | |||
746 | down(&winch_handler_sem); | ||
747 | list_for_each(ele, &winch_handlers){ | ||
748 | winch = list_entry(ele, struct winch, list); | ||
749 | if(winch->tty == tty){ | ||
750 | found = winch; | ||
751 | break; | ||
752 | } | ||
753 | } | ||
754 | |||
755 | if(found == NULL) | ||
756 | goto out; | ||
757 | |||
758 | if(winch->pid != -1) | ||
759 | os_kill_process(winch->pid, 1); | ||
760 | |||
761 | free_irq_by_irq_and_dev(WINCH_IRQ, winch); | ||
762 | free_irq(WINCH_IRQ, winch); | ||
763 | list_del(&winch->list); | ||
764 | kfree(winch); | ||
765 | out: | ||
766 | up(&winch_handler_sem); | ||
767 | } | ||
768 | |||
732 | static void winch_cleanup(void) | 769 | static void winch_cleanup(void) |
733 | { | 770 | { |
734 | struct list_head *ele; | 771 | struct list_head *ele; |
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 07340c8cf203..d246d5a24609 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); | |||
160 | extern void os_kill_ptraced_process(int pid, int reap_child); | 160 | extern void os_kill_ptraced_process(int pid, int reap_child); |
161 | extern void os_usr1_process(int pid); | 161 | extern void os_usr1_process(int pid); |
162 | extern int os_getpid(void); | 162 | extern int os_getpid(void); |
163 | extern int os_getpgrp(void); | ||
163 | 164 | ||
164 | extern int os_map_memory(void *virt, int fd, unsigned long long off, | 165 | extern int os_map_memory(void *virt, int fd, unsigned long long off, |
165 | unsigned long len, int r, int w, int x); | 166 | unsigned long len, int r, int w, int x); |
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index d71e8f00810f..d44fb5282547 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c | |||
@@ -163,7 +163,6 @@ void __init init_IRQ(void) | |||
163 | irq_desc[i].handler = &SIGIO_irq_type; | 163 | irq_desc[i].handler = &SIGIO_irq_type; |
164 | enable_irq(i); | 164 | enable_irq(i); |
165 | } | 165 | } |
166 | init_irq_signals(0); | ||
167 | } | 166 | } |
168 | 167 | ||
169 | /* | 168 | /* |
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index f76a2692adca..51f8e5a8ac6a 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
@@ -65,8 +65,6 @@ void init_new_thread_signals(int altstack) | |||
65 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | 65 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); |
66 | set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, | 66 | set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, |
67 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | 67 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); |
68 | set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, | ||
69 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | ||
70 | set_handler(SIGUSR2, (__sighandler_t) sig_handler, | 68 | set_handler(SIGUSR2, (__sighandler_t) sig_handler, |
71 | flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | 69 | flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); |
72 | signal(SIGHUP, SIG_IGN); | 70 | signal(SIGHUP, SIG_IGN); |
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index 668df13d8c9d..e89218958f38 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) | |||
182 | int i, n, respond_fd; | 182 | int i, n, respond_fd; |
183 | char c; | 183 | char c; |
184 | 184 | ||
185 | signal(SIGWINCH, SIG_IGN); | ||
185 | fds = ¤t_poll; | 186 | fds = ¤t_poll; |
186 | while(1){ | 187 | while(1){ |
187 | n = poll(fds->poll, fds->used, -1); | 188 | n = poll(fds->poll, fds->used, -1); |
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index c0b30515dfb6..4dc13bc8cfd8 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c | |||
@@ -28,10 +28,11 @@ | |||
28 | #include "chan_user.h" | 28 | #include "chan_user.h" |
29 | #include "signal_user.h" | 29 | #include "signal_user.h" |
30 | #include "registers.h" | 30 | #include "registers.h" |
31 | #include "process.h" | ||
31 | 32 | ||
32 | int is_skas_winch(int pid, int fd, void *data) | 33 | int is_skas_winch(int pid, int fd, void *data) |
33 | { | 34 | { |
34 | if(pid != os_getpid()) | 35 | if(pid != os_getpgrp()) |
35 | return(0); | 36 | return(0); |
36 | 37 | ||
37 | register_winch_irq(-1, fd, -1, data); | 38 | 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) | |||
259 | sigjmp_buf **switch_buf = switch_buf_ptr; | 260 | sigjmp_buf **switch_buf = switch_buf_ptr; |
260 | int n; | 261 | int n; |
261 | 262 | ||
263 | set_handler(SIGWINCH, (__sighandler_t) sig_handler, | ||
264 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, | ||
265 | SIGVTALRM, -1); | ||
266 | |||
262 | *fork_buf_ptr = &initial_jmpbuf; | 267 | *fork_buf_ptr = &initial_jmpbuf; |
263 | n = sigsetjmp(initial_jmpbuf, 1); | 268 | n = sigsetjmp(initial_jmpbuf, 1); |
264 | if(n == 0) | 269 | if(n == 0) |
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index f7b1753a025c..d11e7399d7a1 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "kern_util.h" | 26 | #include "kern_util.h" |
27 | #include "chan_user.h" | 27 | #include "chan_user.h" |
28 | #include "ptrace_user.h" | 28 | #include "ptrace_user.h" |
29 | #include "irq_user.h" | ||
29 | #include "mode.h" | 30 | #include "mode.h" |
30 | #include "tt.h" | 31 | #include "tt.h" |
31 | 32 | ||
@@ -33,7 +34,7 @@ static int tracer_winch[2]; | |||
33 | 34 | ||
34 | int is_tracer_winch(int pid, int fd, void *data) | 35 | int is_tracer_winch(int pid, int fd, void *data) |
35 | { | 36 | { |
36 | if(pid != tracing_pid) | 37 | if(pid != os_getpgrp()) |
37 | return(0); | 38 | return(0); |
38 | 39 | ||
39 | register_winch_irq(tracer_winch[0], fd, -1, data); | 40 | register_winch_irq(tracer_winch[0], fd, -1, data); |
@@ -119,6 +120,7 @@ static int signal_tramp(void *arg) | |||
119 | signal(SIGSEGV, (__sighandler_t) sig_handler); | 120 | signal(SIGSEGV, (__sighandler_t) sig_handler); |
120 | set_cmdline("(idle thread)"); | 121 | set_cmdline("(idle thread)"); |
121 | set_init_pid(os_getpid()); | 122 | set_init_pid(os_getpid()); |
123 | init_irq_signals(0); | ||
122 | proc = arg; | 124 | proc = arg; |
123 | return((*proc)(NULL)); | 125 | return((*proc)(NULL)); |
124 | } | 126 | } |
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index ba9ca1cc790a..1e126bfd31a7 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
@@ -123,6 +123,11 @@ int os_getpid(void) | |||
123 | return(getpid()); | 123 | return(getpid()); |
124 | } | 124 | } |
125 | 125 | ||
126 | int os_getpgrp(void) | ||
127 | { | ||
128 | return getpgrp(); | ||
129 | } | ||
130 | |||
126 | int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, | 131 | int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, |
127 | int r, int w, int x) | 132 | int r, int w, int x) |
128 | { | 133 | { |