linux: Retry VT ioctls while errno == EINTR
When the smart scheduler is enabled, the VT ioctls (particularly
VT_WAITACTIVE) can be interrupted by the smart scheduler's SIGALRMs.
Previously, this caused the server to immediately continue on to
ScreenInit, almost certainly causing a crash or failure because the X
server that owned the VT hadn't finished cleaning up. As of commit
7ee965a300
, it causes a FatalError
instead.
Retrying the ioctl as long as it fails with errno == EINTR fixes the
problem and allows server regenerations to trigger VT switches that
actually succeed.
Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Cyril Brulebois <kibi@debian.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
parent
302bdc3c96
commit
88c4622b59
|
@ -62,17 +62,21 @@ drain_console(int fd, void *closure)
|
||||||
static void
|
static void
|
||||||
switch_to(int vt, const char *from)
|
switch_to(int vt, const char *from)
|
||||||
{
|
{
|
||||||
if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, vt) < 0)
|
int ret;
|
||||||
FatalError("%s: VT_ACTIVATE failed: %s\n", from, strerror(errno));
|
|
||||||
|
|
||||||
if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, vt) < 0)
|
SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_ACTIVATE, vt));
|
||||||
FatalError("%s: VT_WAITACTIVE failed: %s\n", from, strerror(errno));
|
if (ret < 0)
|
||||||
|
FatalError("%s: VT_ACTIVATE failed: %s\n", from, strerror(errno));
|
||||||
|
|
||||||
|
SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_WAITACTIVE, vt));
|
||||||
|
if (ret < 0)
|
||||||
|
FatalError("%s: VT_WAITACTIVE failed: %s\n", from, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
xf86OpenConsole(void)
|
xf86OpenConsole(void)
|
||||||
{
|
{
|
||||||
int i, fd = -1;
|
int i, fd = -1, ret;
|
||||||
struct vt_mode VT;
|
struct vt_mode VT;
|
||||||
struct vt_stat vts;
|
struct vt_stat vts;
|
||||||
MessageType from = X_PROBED;
|
MessageType from = X_PROBED;
|
||||||
|
@ -107,17 +111,19 @@ xf86OpenConsole(void)
|
||||||
|
|
||||||
if (ShareVTs)
|
if (ShareVTs)
|
||||||
{
|
{
|
||||||
if (ioctl(fd, VT_GETSTATE, &vts) == 0)
|
SYSCALL(ret = ioctl(fd, VT_GETSTATE, &vts));
|
||||||
xf86Info.vtno = vts.v_active;
|
if (ret < 0)
|
||||||
else
|
FatalError("xf86OpenConsole: Cannot find the current"
|
||||||
FatalError("xf86OpenConsole: Cannot find the current"
|
" VT (%s)\n", strerror(errno));
|
||||||
" VT (%s)\n", strerror(errno));
|
xf86Info.vtno = vts.v_active;
|
||||||
} else {
|
} else {
|
||||||
if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) ||
|
SYSCALL(ret = ioctl(fd, VT_OPENQRY, &xf86Info.vtno));
|
||||||
(xf86Info.vtno == -1))
|
if (ret < 0)
|
||||||
FatalError("xf86OpenConsole: Cannot find a free VT: %s\n",
|
FatalError("xf86OpenConsole: Cannot find a free VT: "
|
||||||
strerror(errno));
|
"%s\n", strerror(errno));
|
||||||
}
|
if (xf86Info.vtno == -1)
|
||||||
|
FatalError("xf86OpenConsole: Cannot find a free VT\n");
|
||||||
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +165,8 @@ xf86OpenConsole(void)
|
||||||
* Linux doesn't switch to an active vt after the last close of a vt,
|
* Linux doesn't switch to an active vt after the last close of a vt,
|
||||||
* so we do this ourselves by remembering which is active now.
|
* so we do this ourselves by remembering which is active now.
|
||||||
*/
|
*/
|
||||||
if (ioctl(xf86Info.consoleFd, VT_GETSTATE, &vts) < 0)
|
SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_GETSTATE, &vts));
|
||||||
|
if (ret < 0)
|
||||||
xf86Msg(X_WARNING,"xf86OpenConsole: VT_GETSTATE failed: %s\n",
|
xf86Msg(X_WARNING,"xf86OpenConsole: VT_GETSTATE failed: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
else
|
else
|
||||||
|
@ -171,7 +178,7 @@ xf86OpenConsole(void)
|
||||||
* Detach from the controlling tty to avoid char loss
|
* Detach from the controlling tty to avoid char loss
|
||||||
*/
|
*/
|
||||||
if ((i = open("/dev/tty",O_RDWR)) >= 0) {
|
if ((i = open("/dev/tty",O_RDWR)) >= 0) {
|
||||||
ioctl(i, TIOCNOTTY, 0);
|
SYSCALL(ioctl(i, TIOCNOTTY, 0));
|
||||||
close(i);
|
close(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,9 +193,10 @@ xf86OpenConsole(void)
|
||||||
*/
|
*/
|
||||||
switch_to(xf86Info.vtno, "xf86OpenConsole");
|
switch_to(xf86Info.vtno, "xf86OpenConsole");
|
||||||
|
|
||||||
if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0)
|
SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_GETMODE, &VT));
|
||||||
FatalError("xf86OpenConsole: VT_GETMODE failed %s\n",
|
if (ret < 0)
|
||||||
strerror(errno));
|
FatalError("xf86OpenConsole: VT_GETMODE failed %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
signal(SIGUSR1, xf86VTRequest);
|
signal(SIGUSR1, xf86VTRequest);
|
||||||
|
|
||||||
|
@ -196,20 +204,23 @@ xf86OpenConsole(void)
|
||||||
VT.relsig = SIGUSR1;
|
VT.relsig = SIGUSR1;
|
||||||
VT.acqsig = SIGUSR1;
|
VT.acqsig = SIGUSR1;
|
||||||
|
|
||||||
if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
|
SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_SETMODE, &VT));
|
||||||
FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed: %s\n",
|
if (ret < 0)
|
||||||
|
FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
|
||||||
if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0)
|
SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS));
|
||||||
FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed %s\n",
|
if (ret < 0)
|
||||||
strerror(errno));
|
FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
tcgetattr(xf86Info.consoleFd, &tty_attr);
|
tcgetattr(xf86Info.consoleFd, &tty_attr);
|
||||||
ioctl(xf86Info.consoleFd, KDGKBMODE, &tty_mode);
|
SYSCALL(ioctl(xf86Info.consoleFd, KDGKBMODE, &tty_mode));
|
||||||
|
|
||||||
if (ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW) < 0)
|
SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW));
|
||||||
FatalError("xf86OpenConsole: KDSKBMODE K_RAW failed %s\n",
|
if (ret < 0)
|
||||||
strerror(errno));
|
FatalError("xf86OpenConsole: KDSKBMODE K_RAW failed %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
nTty = tty_attr;
|
nTty = tty_attr;
|
||||||
nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
|
nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
|
||||||
|
@ -241,6 +252,7 @@ void
|
||||||
xf86CloseConsole(void)
|
xf86CloseConsole(void)
|
||||||
{
|
{
|
||||||
struct vt_mode VT;
|
struct vt_mode VT;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (ShareVTs) {
|
if (ShareVTs) {
|
||||||
close(xf86Info.consoleFd);
|
close(xf86Info.consoleFd);
|
||||||
|
@ -253,20 +265,23 @@ xf86CloseConsole(void)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Back to text mode ... */
|
/* Back to text mode ... */
|
||||||
if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT) < 0)
|
SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT));
|
||||||
|
if (ret < 0)
|
||||||
xf86Msg(X_WARNING, "xf86CloseConsole: KDSETMODE failed: %s\n",
|
xf86Msg(X_WARNING, "xf86CloseConsole: KDSETMODE failed: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
|
||||||
ioctl(xf86Info.consoleFd, KDSKBMODE, tty_mode);
|
SYSCALL(ioctl(xf86Info.consoleFd, KDSKBMODE, tty_mode));
|
||||||
tcsetattr(xf86Info.consoleFd, TCSANOW, &tty_attr);
|
tcsetattr(xf86Info.consoleFd, TCSANOW, &tty_attr);
|
||||||
|
|
||||||
if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0)
|
SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_GETMODE, &VT));
|
||||||
|
if (ret < 0)
|
||||||
xf86Msg(X_WARNING, "xf86CloseConsole: VT_GETMODE failed: %s\n",
|
xf86Msg(X_WARNING, "xf86CloseConsole: VT_GETMODE failed: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
else {
|
else {
|
||||||
/* set dflt vt handling */
|
/* set dflt vt handling */
|
||||||
VT.mode = VT_AUTO;
|
VT.mode = VT_AUTO;
|
||||||
if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
|
SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_SETMODE, &VT));
|
||||||
|
if (ret < 0)
|
||||||
xf86Msg(X_WARNING, "xf86CloseConsole: VT_SETMODE failed: %s\n",
|
xf86Msg(X_WARNING, "xf86CloseConsole: VT_SETMODE failed: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue