Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 May 2015 16:19:02 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r282645 - head/sys/dev/vt
Message-ID:  <201505081619.t48GJ239054061@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Fri May  8 16:19:01 2015
New Revision: 282645
URL: https://svnweb.freebsd.org/changeset/base/282645

Log:
  Prevent switching to NULL or own window in the "vt_proc_window_switch"
  function. This fixes an issue where X11 keyboard input can appear
  stuck. The cause of the problem is a duplicate TTY device window
  switch IOCTL during boot, which leaves the "vt_switch_timer" running,
  because the current window is already selected. While at it factor out
  some NULL checks.
  
  PR:			200032
  Differential Revision:	https://reviews.freebsd.org/D2480
  Reported by:		several people
  MFC after:		1 week
  Reviewed by:		emaste

Modified:
  head/sys/dev/vt/vt_core.c

Modified: head/sys/dev/vt/vt_core.c
==============================================================================
--- head/sys/dev/vt/vt_core.c	Fri May  8 16:18:11 2015	(r282644)
+++ head/sys/dev/vt/vt_core.c	Fri May  8 16:19:01 2015	(r282645)
@@ -451,12 +451,35 @@ vt_proc_window_switch(struct vt_window *
 	struct vt_device *vd;
 	int ret;
 
+	/* Prevent switching to NULL */
+	if (vw == NULL) {
+		DPRINTF(30, "%s: Cannot switch: vw is NULL.", __func__);
+		return (EINVAL);
+	}
 	vd = vw->vw_device;
 	curvw = vd->vd_curwindow;
 
+	/* Check if virtual terminal is locked */
 	if (curvw->vw_flags & VWF_VTYLOCK)
 		return (EBUSY);
 
+	/* Check if switch already in progress */
+	if (curvw->vw_flags & VWF_SWWAIT_REL) {
+		/* Check if switching to same window */
+		if (curvw->vw_switch_to == vw) {
+			DPRINTF(30, "%s: Switch in progress to same vw.", __func__);
+			return (0);	/* success */
+		}
+		DPRINTF(30, "%s: Switch in progress to different vw.", __func__);
+		return (EBUSY);
+	}
+
+	/* Avoid switching to already selected window */
+	if (vw == curvw) {
+		DPRINTF(30, "%s: Cannot switch: vw == curvw.", __func__);
+		return (0);	/* success */
+	}
+
 	/* Ask current process permission to switch away. */
 	if (curvw->vw_smode.mode == VT_PROCESS) {
 		DPRINTF(30, "%s: VT_PROCESS ", __func__);
@@ -664,8 +687,7 @@ vt_scrollmode_kbdevent(struct vt_window 
 	if (console == 0) {
 		if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
 			vw = vd->vd_windows[c - F_SCR];
-			if (vw != NULL)
-				vt_proc_window_switch(vw);
+			vt_proc_window_switch(vw);
 			return;
 		}
 		VT_LOCK(vd);
@@ -750,8 +772,7 @@ vt_processkey(keyboard_t *kbd, struct vt
 
 		if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
 			vw = vd->vd_windows[c - F_SCR];
-			if (vw != NULL)
-				vt_proc_window_switch(vw);
+			vt_proc_window_switch(vw);
 			return (0);
 		}
 
@@ -760,15 +781,13 @@ vt_processkey(keyboard_t *kbd, struct vt
 			/* Switch to next VT. */
 			c = (vw->vw_number + 1) % VT_MAXWINDOWS;
 			vw = vd->vd_windows[c];
-			if (vw != NULL)
-				vt_proc_window_switch(vw);
+			vt_proc_window_switch(vw);
 			return (0);
 		case PREV:
 			/* Switch to previous VT. */
 			c = (vw->vw_number - 1) % VT_MAXWINDOWS;
 			vw = vd->vd_windows[c];
-			if (vw != NULL)
-				vt_proc_window_switch(vw);
+			vt_proc_window_switch(vw);
 			return (0);
 		case SLK: {
 			vt_save_kbd_state(vw, kbd);
@@ -2774,8 +2793,7 @@ vt_resume(struct vt_device *vd)
 
 	if (vt_suspendswitch == 0)
 		return;
-	/* Switch back to saved window */
-	if (vd->vd_savedwindow != NULL)
-		vt_proc_window_switch(vd->vd_savedwindow);
+	/* Switch back to saved window, if any */
+	vt_proc_window_switch(vd->vd_savedwindow);
 	vd->vd_savedwindow = NULL;
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505081619.t48GJ239054061>