aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2005-05-05 19:15:32 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-05 19:36:36 -0400
commitcd2ee4a30cc0775d8b54e5b958613361a7cacfec (patch)
treeedea72ea7d723a1c35675632850916d77084581b /arch/um
parentc578455a3eccf4dd7bd111e77129c301d6d67914 (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/um')
-rw-r--r--arch/um/drivers/line.c41
-rw-r--r--arch/um/include/os.h1
-rw-r--r--arch/um/kernel/irq.c1
-rw-r--r--arch/um/kernel/process.c2
-rw-r--r--arch/um/kernel/sigio_user.c1
-rw-r--r--arch/um/kernel/skas/process.c7
-rw-r--r--arch/um/kernel/tt/tracer.c4
-rw-r--r--arch/um/os-Linux/process.c5
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
465static void unregister_winch(struct tty_struct *tty);
466
465void line_close(struct tty_struct *tty, struct file * filp) 467void 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
741static 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
732static void winch_cleanup(void) 769static 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);
160extern void os_kill_ptraced_process(int pid, int reap_child); 160extern void os_kill_ptraced_process(int pid, int reap_child);
161extern void os_usr1_process(int pid); 161extern void os_usr1_process(int pid);
162extern int os_getpid(void); 162extern int os_getpid(void);
163extern int os_getpgrp(void);
163 164
164extern int os_map_memory(void *virt, int fd, unsigned long long off, 165extern 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 = &current_poll; 186 fds = &current_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
32int is_skas_winch(int pid, int fd, void *data) 33int 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
34int is_tracer_winch(int pid, int fd, void *data) 35int 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
126int os_getpgrp(void)
127{
128 return getpgrp();
129}
130
126int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, 131int 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{