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
This commit is contained in:
parent
57645743ad
commit
d0e1b4c12c
@ -451,12 +451,35 @@ vt_proc_window_switch(struct vt_window *vw)
|
|||||||
struct vt_device *vd;
|
struct vt_device *vd;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* Prevent switching to NULL */
|
||||||
|
if (vw == NULL) {
|
||||||
|
DPRINTF(30, "%s: Cannot switch: vw is NULL.", __func__);
|
||||||
|
return (EINVAL);
|
||||||
|
}
|
||||||
vd = vw->vw_device;
|
vd = vw->vw_device;
|
||||||
curvw = vd->vd_curwindow;
|
curvw = vd->vd_curwindow;
|
||||||
|
|
||||||
|
/* Check if virtual terminal is locked */
|
||||||
if (curvw->vw_flags & VWF_VTYLOCK)
|
if (curvw->vw_flags & VWF_VTYLOCK)
|
||||||
return (EBUSY);
|
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. */
|
/* Ask current process permission to switch away. */
|
||||||
if (curvw->vw_smode.mode == VT_PROCESS) {
|
if (curvw->vw_smode.mode == VT_PROCESS) {
|
||||||
DPRINTF(30, "%s: VT_PROCESS ", __func__);
|
DPRINTF(30, "%s: VT_PROCESS ", __func__);
|
||||||
@ -664,8 +687,7 @@ vt_scrollmode_kbdevent(struct vt_window *vw, int c, int console)
|
|||||||
if (console == 0) {
|
if (console == 0) {
|
||||||
if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
|
if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
|
||||||
vw = vd->vd_windows[c - F_SCR];
|
vw = vd->vd_windows[c - F_SCR];
|
||||||
if (vw != NULL)
|
vt_proc_window_switch(vw);
|
||||||
vt_proc_window_switch(vw);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
VT_LOCK(vd);
|
VT_LOCK(vd);
|
||||||
@ -750,8 +772,7 @@ vt_processkey(keyboard_t *kbd, struct vt_device *vd, int c)
|
|||||||
|
|
||||||
if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
|
if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
|
||||||
vw = vd->vd_windows[c - F_SCR];
|
vw = vd->vd_windows[c - F_SCR];
|
||||||
if (vw != NULL)
|
vt_proc_window_switch(vw);
|
||||||
vt_proc_window_switch(vw);
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,15 +781,13 @@ vt_processkey(keyboard_t *kbd, struct vt_device *vd, int c)
|
|||||||
/* Switch to next VT. */
|
/* Switch to next VT. */
|
||||||
c = (vw->vw_number + 1) % VT_MAXWINDOWS;
|
c = (vw->vw_number + 1) % VT_MAXWINDOWS;
|
||||||
vw = vd->vd_windows[c];
|
vw = vd->vd_windows[c];
|
||||||
if (vw != NULL)
|
vt_proc_window_switch(vw);
|
||||||
vt_proc_window_switch(vw);
|
|
||||||
return (0);
|
return (0);
|
||||||
case PREV:
|
case PREV:
|
||||||
/* Switch to previous VT. */
|
/* Switch to previous VT. */
|
||||||
c = (vw->vw_number - 1) % VT_MAXWINDOWS;
|
c = (vw->vw_number - 1) % VT_MAXWINDOWS;
|
||||||
vw = vd->vd_windows[c];
|
vw = vd->vd_windows[c];
|
||||||
if (vw != NULL)
|
vt_proc_window_switch(vw);
|
||||||
vt_proc_window_switch(vw);
|
|
||||||
return (0);
|
return (0);
|
||||||
case SLK: {
|
case SLK: {
|
||||||
vt_save_kbd_state(vw, kbd);
|
vt_save_kbd_state(vw, kbd);
|
||||||
@ -2774,8 +2793,7 @@ vt_resume(struct vt_device *vd)
|
|||||||
|
|
||||||
if (vt_suspendswitch == 0)
|
if (vt_suspendswitch == 0)
|
||||||
return;
|
return;
|
||||||
/* Switch back to saved window */
|
/* Switch back to saved window, if any */
|
||||||
if (vd->vd_savedwindow != NULL)
|
vt_proc_window_switch(vd->vd_savedwindow);
|
||||||
vt_proc_window_switch(vd->vd_savedwindow);
|
|
||||||
vd->vd_savedwindow = NULL;
|
vd->vd_savedwindow = NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user