diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 5d1289d3341013196c211fda633c69f73435adfc..8b81bd5f20f2ff4c6fb6b11414d0bfdc0bd79679 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -51,19 +51,21 @@ int generic_console_write(int fd, const char *buf, int n)
 /*
  * UML SIGWINCH handling
  *
- * The point of this is to handle SIGWINCH on consoles which have host ttys and
- * relay them inside UML to whatever might be running on the console and cares
- * about the window size (since SIGWINCH notifies about terminal size changes).
+ * The point of this is to handle SIGWINCH on consoles which have host
+ * ttys and relay them inside UML to whatever might be running on the
+ * console and cares about the window size (since SIGWINCH notifies
+ * about terminal size changes).
  *
- * So, we have a separate thread for each host tty attached to a UML device
- * (side-issue - I'm annoyed that one thread can't have multiple controlling
- * ttys for purposed of handling SIGWINCH, but I imagine there are other reasons
- * that doesn't make any sense).
+ * So, we have a separate thread for each host tty attached to a UML
+ * device (side-issue - I'm annoyed that one thread can't have
+ * multiple controlling ttys for the purpose of handling SIGWINCH, but
+ * I imagine there are other reasons that doesn't make any sense).
  *
- * SIGWINCH can't be received synchronously, so you have to set up to receive it
- * as a signal.  That being the case, if you are going to wait for it, it is
- * convenient to sit in sigsuspend() and wait for the signal to bounce you out of
- * it (see below for how we make sure to exit only on SIGWINCH).
+ * SIGWINCH can't be received synchronously, so you have to set up to
+ * receive it as a signal.  That being the case, if you are going to
+ * wait for it, it is convenient to sit in sigsuspend() and wait for
+ * the signal to bounce you out of it (see below for how we make sure
+ * to exit only on SIGWINCH).
  */
 
 static void winch_handler(int sig)
@@ -112,7 +114,8 @@ static int winch_thread(void *arg)
 
 	err = os_new_tty_pgrp(pty_fd, os_getpid());
 	if(err < 0){
-		printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err);
+		printk("winch_thread : new_tty_pgrp failed on fd %d, "
+		       "err = %d\n", pty_fd, -err);
 		exit(1);
 	}
 
@@ -126,8 +129,9 @@ static int winch_thread(void *arg)
 		       "err = %d\n", -count);
 
 	while(1){
-		/* This will be interrupted by SIGWINCH only, since other signals
-		 * are blocked.*/
+		/* This will be interrupted by SIGWINCH only, since
+		 * other signals are blocked.
+		 */
 		sigsuspend(&sigs);
 
 		count = os_write_file(pipe_fd, &c, sizeof(c));
@@ -137,10 +141,10 @@ static int winch_thread(void *arg)
 	}
 }
 
-static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
+static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
+		       unsigned long *stack_out)
 {
 	struct winch_data data;
-	unsigned long stack;
 	int fds[2], n, err;
 	char c;
 
@@ -153,9 +157,11 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
 	data = ((struct winch_data) { .pty_fd 		= fd,
 				      .pipe_fd 		= fds[1] } );
 	/* CLONE_FILES so this thread doesn't hold open files which are open
-	 * now, but later closed.  This is a problem with /dev/net/tun.
+	 * now, but later closed in a different thread.  This is a
+	 * problem with /dev/net/tun, which if held open by this
+	 * thread, prevents the TUN/TAP device from being reused.
 	 */
-	err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0);
+	err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out, 0);
 	if(err < 0){
 		printk("fork of winch_thread failed - errno = %d\n", -err);
 		goto out_close;
@@ -187,25 +193,25 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
 
 void register_winch(int fd, struct tty_struct *tty)
 {
-	int pid, thread, thread_fd = -1;
-	int count;
+	unsigned long stack;
+	int pid, thread, count, thread_fd = -1;
 	char c = 1;
 
 	if(!isatty(fd))
 		return;
 
 	pid = tcgetpgrp(fd);
-	if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
-			     tty) && (pid == -1)){
-		thread = winch_tramp(fd, tty, &thread_fd);
-		if(thread > 0){
-			register_winch_irq(thread_fd, fd, thread, tty);
-
-			count = os_write_file(thread_fd, &c, sizeof(c));
-			if(count != sizeof(c))
-				printk("register_winch : failed to write "
-				       "synchronization byte, err = %d\n",
-					-count);
-		}
+	if (!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, tty) &&
+	    (pid == -1)) {
+		thread = winch_tramp(fd, tty, &thread_fd, &stack);
+		if (thread < 0)
+			return;
+
+		register_winch_irq(thread_fd, fd, thread, tty, stack);
+
+		count = os_write_file(thread_fd, &c, sizeof(c));
+		if(count != sizeof(c))
+			printk("register_winch : failed to write "
+			       "synchronization byte, err = %d\n", -count);
 	}
 }
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 1fb3e51108b9057bfbb2b3ff66ea67c4a3b397fe..3e0b68e297f2426a3701c4acc0c62a332c0b85ee 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -749,8 +749,24 @@ struct winch {
 	int tty_fd;
 	int pid;
 	struct tty_struct *tty;
+	unsigned long stack;
 };
 
+static void free_winch(struct winch *winch, int free_irq_ok)
+{
+	list_del(&winch->list);
+
+	if (winch->pid != -1)
+		os_kill_process(winch->pid, 1);
+	if (winch->fd != -1)
+		os_close_file(winch->fd);
+	if (winch->stack != 0)
+		free_stack(winch->stack, 0);
+	if (free_irq_ok)
+		free_irq(WINCH_IRQ, winch);
+	kfree(winch);
+}
+
 static irqreturn_t winch_interrupt(int irq, void *data)
 {
 	struct winch *winch = data;
@@ -767,12 +783,13 @@ static irqreturn_t winch_interrupt(int irq, void *data)
 				       "errno = %d\n", -err);
 				printk("fd %d is losing SIGWINCH support\n",
 				       winch->tty_fd);
+				free_winch(winch, 0);
 				return IRQ_HANDLED;
 			}
 			goto out;
 		}
 	}
-	tty  = winch->tty;
+	tty = winch->tty;
 	if (tty != NULL) {
 		line = tty->driver_data;
 		chan_window_size(&line->chan_list, &tty->winsize.ws_row,
@@ -785,43 +802,44 @@ static irqreturn_t winch_interrupt(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
+void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
+			unsigned long stack)
 {
 	struct winch *winch;
 
 	winch = kmalloc(sizeof(*winch), GFP_KERNEL);
 	if (winch == NULL) {
 		printk("register_winch_irq - kmalloc failed\n");
-		return;
+		goto cleanup;
 	}
 
 	*winch = ((struct winch) { .list  	= LIST_HEAD_INIT(winch->list),
 				   .fd  	= fd,
 				   .tty_fd 	= tty_fd,
 				   .pid  	= pid,
-				   .tty 	= tty });
+				   .tty 	= tty,
+				   .stack	= stack });
+
+	if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
+			   IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			   "winch", winch) < 0) {
+		printk("register_winch_irq - failed to register IRQ\n");
+		goto out_free;
+	}
 
 	spin_lock(&winch_handler_lock);
 	list_add(&winch->list, &winch_handlers);
 	spin_unlock(&winch_handler_lock);
 
-	if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
-			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-			  "winch", winch) < 0)
-		printk("register_winch_irq - failed to register IRQ\n");
-}
-
-static void free_winch(struct winch *winch)
-{
-	list_del(&winch->list);
-
-	if(winch->pid != -1)
-		os_kill_process(winch->pid, 1);
-	if(winch->fd != -1)
-		os_close_file(winch->fd);
+	return;
 
-	free_irq(WINCH_IRQ, winch);
+ out_free:
 	kfree(winch);
+ cleanup:
+	os_kill_process(pid, 1);
+	os_close_file(fd);
+	if (stack != 0)
+		free_stack(stack, 0);
 }
 
 static void unregister_winch(struct tty_struct *tty)
@@ -834,7 +852,7 @@ static void unregister_winch(struct tty_struct *tty)
 	list_for_each(ele, &winch_handlers){
 		winch = list_entry(ele, struct winch, list);
                 if(winch->tty == tty){
-			free_winch(winch);
+			free_winch(winch, 1);
 			break;
                 }
         }
@@ -850,7 +868,7 @@ static void winch_cleanup(void)
 
 	list_for_each_safe(ele, next, &winch_handlers){
 		winch = list_entry(ele, struct winch, list);
-		free_winch(winch);
+		free_winch(winch, 1);
 	}
 
 	spin_unlock(&winch_handler_lock);
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 714b713e2e72745614a8f52feb32c53de7206267..5a2263e05bb20cb62bf5b8f7eecc02cde8d324b6 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -42,7 +42,8 @@ extern void generic_free(void *data);
 
 struct tty_struct;
 extern void register_winch(int fd,  struct tty_struct *tty);
-extern void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty);
+extern void register_winch_irq(int fd, int tty_fd, int pid,
+			       struct tty_struct *tty, unsigned long stack);
 
 #define __channel_help(fn, prefix) \
 __uml_help(fn, prefix "[0-9]*=<channel description>\n" \
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 46c00cc429bc70e49ba12bfb97b3c4eb88ff2b32..ba9af8d62055299dcf005dabe9248d5a381df030 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -41,7 +41,7 @@ int is_skas_winch(int pid, int fd, void *data)
 	if(pid != os_getpgrp())
 		return(0);
 
-	register_winch_irq(-1, fd, -1, data);
+	register_winch_irq(-1, fd, -1, data, 0);
 	return(1);
 }