[PATCH 12/22] UML - Fix SIGWINCH relaying

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <[email protected]>

Index: linux-2.6.11-mm/arch/um/drivers/line.c
===================================================================
--- linux-2.6.11-mm.orig/arch/um/drivers/line.c	2005-04-30 12:57:43.000000000 -0400
+++ linux-2.6.11-mm/arch/um/drivers/line.c	2005-04-30 13:09:17.000000000 -0400
@@ -462,12 +462,15 @@
 	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 @@
 		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 @@
 	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;
Index: linux-2.6.11-mm/arch/um/include/os.h
===================================================================
--- linux-2.6.11-mm.orig/arch/um/include/os.h	2005-04-30 12:56:24.000000000 -0400
+++ linux-2.6.11-mm/arch/um/include/os.h	2005-04-30 13:08:14.000000000 -0400
@@ -160,6 +160,7 @@
 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);
Index: linux-2.6.11-mm/arch/um/kernel/irq.c
===================================================================
--- linux-2.6.11-mm.orig/arch/um/kernel/irq.c	2005-04-30 12:56:24.000000000 -0400
+++ linux-2.6.11-mm/arch/um/kernel/irq.c	2005-04-30 13:08:14.000000000 -0400
@@ -163,7 +163,6 @@
 		irq_desc[i].handler = &SIGIO_irq_type;
 		enable_irq(i);
 	}
-	init_irq_signals(0);
 }
 
 /*
Index: linux-2.6.11-mm/arch/um/kernel/process.c
===================================================================
--- linux-2.6.11-mm.orig/arch/um/kernel/process.c	2005-04-30 12:56:24.000000000 -0400
+++ linux-2.6.11-mm/arch/um/kernel/process.c	2005-04-30 13:08:14.000000000 -0400
@@ -65,8 +65,6 @@
 		    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);
Index: linux-2.6.11-mm/arch/um/kernel/sigio_user.c
===================================================================
--- linux-2.6.11-mm.orig/arch/um/kernel/sigio_user.c	2005-04-30 12:56:24.000000000 -0400
+++ linux-2.6.11-mm/arch/um/kernel/sigio_user.c	2005-04-30 13:08:14.000000000 -0400
@@ -182,6 +182,7 @@
 	int i, n, respond_fd;
 	char c;
 
+        signal(SIGWINCH, SIG_IGN);
 	fds = &current_poll;
 	while(1){
 		n = poll(fds->poll, fds->used, -1);
Index: linux-2.6.11-mm/arch/um/kernel/skas/process.c
===================================================================
--- linux-2.6.11-mm.orig/arch/um/kernel/skas/process.c	2005-04-30 13:08:02.000000000 -0400
+++ linux-2.6.11-mm/arch/um/kernel/skas/process.c	2005-04-30 13:08:14.000000000 -0400
@@ -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 @@
 	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)
Index: linux-2.6.11-mm/arch/um/kernel/tt/tracer.c
===================================================================
--- linux-2.6.11-mm.orig/arch/um/kernel/tt/tracer.c	2005-04-30 13:08:02.000000000 -0400
+++ linux-2.6.11-mm/arch/um/kernel/tt/tracer.c	2005-04-30 13:08:14.000000000 -0400
@@ -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 @@
 
 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 @@
 	signal(SIGSEGV, (__sighandler_t) sig_handler);
 	set_cmdline("(idle thread)");
 	set_init_pid(os_getpid());
+	init_irq_signals(0);
 	proc = arg;
 	return((*proc)(NULL));
 }
Index: linux-2.6.11-mm/arch/um/os-Linux/process.c
===================================================================
--- linux-2.6.11-mm.orig/arch/um/os-Linux/process.c	2005-04-30 12:56:24.000000000 -0400
+++ linux-2.6.11-mm/arch/um/os-Linux/process.c	2005-04-30 13:08:14.000000000 -0400
@@ -123,6 +123,11 @@
 	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)
 {

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux