[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>
This commit is contained in:
parent
c578455a3e
commit
cd2ee4a30c
|
@ -462,12 +462,15 @@ out:
|
|||
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -163,7 +163,6 @@ void __init init_IRQ(void)
|
|||
irq_desc[i].handler = &SIGIO_irq_type;
|
||||
enable_irq(i);
|
||||
}
|
||||
init_irq_signals(0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue