Commit cd2ee4a30cc0775d8b54e5b958613361a7cacfec

Authored by Jeff Dike
Committed by Linus Torvalds
1 parent c578455a3e

[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>

Showing 8 changed files with 55 additions and 7 deletions Side-by-side Diff

arch/um/drivers/line.c
... ... @@ -462,12 +462,15 @@
462 462 return err;
463 463 }
464 464  
  465 +static void unregister_winch(struct tty_struct *tty);
  466 +
465 467 void line_close(struct tty_struct *tty, struct file * filp)
466 468 {
467 469 struct line *line = tty->driver_data;
468 470  
469   - /* XXX: I assume this should be called in process context, not with interrupt
470   - * disabled!*/
  471 + /* XXX: I assume this should be called in process context, not with
  472 + * interrupts disabled!
  473 + */
471 474 spin_lock_irq(&line->lock);
472 475  
473 476 /* We ignore the error anyway! */
... ... @@ -478,6 +481,12 @@
478 481 line_disable(tty, -1);
479 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 490 spin_unlock_irq(&line->lock);
482 491 }
483 492  
... ... @@ -725,6 +734,34 @@
725 734 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
726 735 "winch", winch) < 0)
727 736 printk("register_winch_irq - failed to register IRQ\n");
  737 + out:
  738 + up(&winch_handler_sem);
  739 +}
  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);
728 765 out:
729 766 up(&winch_handler_sem);
730 767 }
arch/um/include/os.h
... ... @@ -160,6 +160,7 @@
160 160 extern void os_kill_ptraced_process(int pid, int reap_child);
161 161 extern void os_usr1_process(int pid);
162 162 extern int os_getpid(void);
  163 +extern int os_getpgrp(void);
163 164  
164 165 extern int os_map_memory(void *virt, int fd, unsigned long long off,
165 166 unsigned long len, int r, int w, int x);
arch/um/kernel/irq.c
... ... @@ -163,7 +163,6 @@
163 163 irq_desc[i].handler = &SIGIO_irq_type;
164 164 enable_irq(i);
165 165 }
166   - init_irq_signals(0);
167 166 }
168 167  
169 168 /*
arch/um/kernel/process.c
... ... @@ -65,8 +65,6 @@
65 65 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
66 66 set_handler(SIGBUS, (__sighandler_t) sig_handler, flags,
67 67 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
68   - set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags,
69   - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
70 68 set_handler(SIGUSR2, (__sighandler_t) sig_handler,
71 69 flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
72 70 signal(SIGHUP, SIG_IGN);
arch/um/kernel/sigio_user.c
... ... @@ -182,6 +182,7 @@
182 182 int i, n, respond_fd;
183 183 char c;
184 184  
  185 + signal(SIGWINCH, SIG_IGN);
185 186 fds = &current_poll;
186 187 while(1){
187 188 n = poll(fds->poll, fds->used, -1);
arch/um/kernel/skas/process.c
... ... @@ -28,10 +28,11 @@
28 28 #include "chan_user.h"
29 29 #include "signal_user.h"
30 30 #include "registers.h"
  31 +#include "process.h"
31 32  
32 33 int is_skas_winch(int pid, int fd, void *data)
33 34 {
34   - if(pid != os_getpid())
  35 + if(pid != os_getpgrp())
35 36 return(0);
36 37  
37 38 register_winch_irq(-1, fd, -1, data);
... ... @@ -258,6 +259,10 @@
258 259 {
259 260 sigjmp_buf **switch_buf = switch_buf_ptr;
260 261 int n;
  262 +
  263 + set_handler(SIGWINCH, (__sighandler_t) sig_handler,
  264 + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
  265 + SIGVTALRM, -1);
261 266  
262 267 *fork_buf_ptr = &initial_jmpbuf;
263 268 n = sigsetjmp(initial_jmpbuf, 1);
arch/um/kernel/tt/tracer.c
... ... @@ -26,6 +26,7 @@
26 26 #include "kern_util.h"
27 27 #include "chan_user.h"
28 28 #include "ptrace_user.h"
  29 +#include "irq_user.h"
29 30 #include "mode.h"
30 31 #include "tt.h"
31 32  
... ... @@ -33,7 +34,7 @@
33 34  
34 35 int is_tracer_winch(int pid, int fd, void *data)
35 36 {
36   - if(pid != tracing_pid)
  37 + if(pid != os_getpgrp())
37 38 return(0);
38 39  
39 40 register_winch_irq(tracer_winch[0], fd, -1, data);
... ... @@ -119,6 +120,7 @@
119 120 signal(SIGSEGV, (__sighandler_t) sig_handler);
120 121 set_cmdline("(idle thread)");
121 122 set_init_pid(os_getpid());
  123 + init_irq_signals(0);
122 124 proc = arg;
123 125 return((*proc)(NULL));
124 126 }
arch/um/os-Linux/process.c
... ... @@ -123,6 +123,11 @@
123 123 return(getpid());
124 124 }
125 125  
  126 +int os_getpgrp(void)
  127 +{
  128 + return getpgrp();
  129 +}
  130 +
126 131 int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
127 132 int r, int w, int x)
128 133 {