Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+39 −2
Original line number Diff line number Diff line
@@ -462,12 +462,15 @@ int line_open(struct line *lines, struct tty_struct *tty,
	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;
+1 −0
Original line number Diff line number Diff line
@@ -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);
+0 −1
Original line number Diff line number Diff line
@@ -163,7 +163,6 @@ void __init init_IRQ(void)
		irq_desc[i].handler = &SIGIO_irq_type;
		enable_irq(i);
	}
	init_irq_signals(0);
}

/*
+0 −2
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ static int write_sigio_thread(void *unused)
	int i, n, respond_fd;
	char c;

        signal(SIGWINCH, SIG_IGN);
	fds = &current_poll;
	while(1){
		n = poll(fds->poll, fds->used, -1);
Loading