Commit cd2ee4a3 authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

[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: default avatarJeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent c578455a
...@@ -462,12 +462,15 @@ out: ...@@ -462,12 +462,15 @@ out:
return err; return err;
} }
static void unregister_winch(struct tty_struct *tty);
void line_close(struct tty_struct *tty, struct file * filp) void line_close(struct tty_struct *tty, struct file * filp)
{ {
struct line *line = tty->driver_data; struct line *line = tty->driver_data;
/* XXX: I assume this should be called in process context, not with interrupt /* XXX: I assume this should be called in process context, not with
* disabled!*/ * interrupts disabled!
*/
spin_lock_irq(&line->lock); spin_lock_irq(&line->lock);
/* We ignore the error anyway! */ /* We ignore the error anyway! */
...@@ -478,6 +481,12 @@ void line_close(struct tty_struct *tty, struct file * filp) ...@@ -478,6 +481,12 @@ void line_close(struct tty_struct *tty, struct file * filp)
line_disable(tty, -1); line_disable(tty, -1);
tty->driver_data = NULL; tty->driver_data = NULL;
} }
if((line->count == 0) && line->sigio){
unregister_winch(tty);
line->sigio = 0;
}
spin_unlock_irq(&line->lock); spin_unlock_irq(&line->lock);
} }
...@@ -729,6 +738,34 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) ...@@ -729,6 +738,34 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
up(&winch_handler_sem); 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) static void winch_cleanup(void)
{ {
struct list_head *ele; struct list_head *ele;
......
...@@ -160,6 +160,7 @@ extern void os_kill_process(int pid, int reap_child); ...@@ -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_kill_ptraced_process(int pid, int reap_child);
extern void os_usr1_process(int pid); extern void os_usr1_process(int pid);
extern int os_getpid(void); extern int os_getpid(void);
extern int os_getpgrp(void);
extern int os_map_memory(void *virt, int fd, unsigned long long off, extern int os_map_memory(void *virt, int fd, unsigned long long off,
unsigned long len, int r, int w, int x); unsigned long len, int r, int w, int x);
......
...@@ -163,7 +163,6 @@ void __init init_IRQ(void) ...@@ -163,7 +163,6 @@ void __init init_IRQ(void)
irq_desc[i].handler = &SIGIO_irq_type; irq_desc[i].handler = &SIGIO_irq_type;
enable_irq(i); enable_irq(i);
} }
init_irq_signals(0);
} }
/* /*
......
...@@ -65,8 +65,6 @@ void init_new_thread_signals(int altstack) ...@@ -65,8 +65,6 @@ void init_new_thread_signals(int altstack)
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, set_handler(SIGBUS, (__sighandler_t) sig_handler, flags,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); 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, set_handler(SIGUSR2, (__sighandler_t) sig_handler,
flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
signal(SIGHUP, SIG_IGN); signal(SIGHUP, SIG_IGN);
......
...@@ -182,6 +182,7 @@ static int write_sigio_thread(void *unused) ...@@ -182,6 +182,7 @@ static int write_sigio_thread(void *unused)
int i, n, respond_fd; int i, n, respond_fd;
char c; char c;
signal(SIGWINCH, SIG_IGN);
fds = &current_poll; fds = &current_poll;
while(1){ while(1){
n = poll(fds->poll, fds->used, -1); n = poll(fds->poll, fds->used, -1);
......
...@@ -28,10 +28,11 @@ ...@@ -28,10 +28,11 @@
#include "chan_user.h" #include "chan_user.h"
#include "signal_user.h" #include "signal_user.h"
#include "registers.h" #include "registers.h"
#include "process.h"
int is_skas_winch(int pid, int fd, void *data) int is_skas_winch(int pid, int fd, void *data)
{ {
if(pid != os_getpid()) if(pid != os_getpgrp())
return(0); return(0);
register_winch_irq(-1, fd, -1, data); 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,6 +260,10 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
sigjmp_buf **switch_buf = switch_buf_ptr; sigjmp_buf **switch_buf = switch_buf_ptr;
int n; int n;
set_handler(SIGWINCH, (__sighandler_t) sig_handler,
SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
SIGVTALRM, -1);
*fork_buf_ptr = &initial_jmpbuf; *fork_buf_ptr = &initial_jmpbuf;
n = sigsetjmp(initial_jmpbuf, 1); n = sigsetjmp(initial_jmpbuf, 1);
if(n == 0) if(n == 0)
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "kern_util.h" #include "kern_util.h"
#include "chan_user.h" #include "chan_user.h"
#include "ptrace_user.h" #include "ptrace_user.h"
#include "irq_user.h"
#include "mode.h" #include "mode.h"
#include "tt.h" #include "tt.h"
...@@ -33,7 +34,7 @@ static int tracer_winch[2]; ...@@ -33,7 +34,7 @@ static int tracer_winch[2];
int is_tracer_winch(int pid, int fd, void *data) int is_tracer_winch(int pid, int fd, void *data)
{ {
if(pid != tracing_pid) if(pid != os_getpgrp())
return(0); return(0);
register_winch_irq(tracer_winch[0], fd, -1, data); register_winch_irq(tracer_winch[0], fd, -1, data);
...@@ -119,6 +120,7 @@ static int signal_tramp(void *arg) ...@@ -119,6 +120,7 @@ static int signal_tramp(void *arg)
signal(SIGSEGV, (__sighandler_t) sig_handler); signal(SIGSEGV, (__sighandler_t) sig_handler);
set_cmdline("(idle thread)"); set_cmdline("(idle thread)");
set_init_pid(os_getpid()); set_init_pid(os_getpid());
init_irq_signals(0);
proc = arg; proc = arg;
return((*proc)(NULL)); return((*proc)(NULL));
} }
......
...@@ -123,6 +123,11 @@ int os_getpid(void) ...@@ -123,6 +123,11 @@ int os_getpid(void)
return(getpid()); return(getpid());
} }
int os_getpgrp(void)
{
return getpgrp();
}
int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
int r, int w, int x) int r, int w, int x)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment