mirror of
https://github.com/troglobit/editline.git
synced 2025-05-06 04:21:24 +08:00
src/sysunix.c: Restart syscalls on spurious EINTR
Handle tcgetattr(), tcsetattr() and ioctl() by wrapping them in a retry-loop and restarting them when receiving EINTR. Should fix problem with sporadic error messages on the console like this one: 'Failed tcsetattr: Interrupted system call' Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
parent
29b7f91165
commit
08b7f57c98
@ -18,20 +18,75 @@
|
||||
* ever read sources, credits must appear in the documentation.
|
||||
* 4. This notice may not be removed or altered.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "editline.h"
|
||||
|
||||
#ifndef HAVE_TCGETATTR
|
||||
/* Wrapper for ioctl syscalls to restart on signal */
|
||||
static int ioctl_wrap(int fd, int req, void *arg)
|
||||
{
|
||||
int result, retries = 3;
|
||||
|
||||
while (-1 == (result = ioctl(fd, req, arg)) && retries > 0) {
|
||||
retries--;
|
||||
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Prefer termios over the others since it is likely the most portable. */
|
||||
#if defined(HAVE_TCGETATTR)
|
||||
#include <termios.h>
|
||||
|
||||
/* Wrapper for tcgetattr */
|
||||
static int getattr(int fd, struct termios *arg)
|
||||
{
|
||||
int result, retries = 3;
|
||||
|
||||
while (-1 == (result = tcgetattr(fd, arg)) && retries > 0) {
|
||||
retries--;
|
||||
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wrapper for tcgetattr */
|
||||
static int setattr(int fd, int opt, const struct termios *arg)
|
||||
{
|
||||
int result, retries = 3;
|
||||
|
||||
while (-1 == (result = tcsetattr(fd, opt, arg)) && retries > 0) {
|
||||
retries--;
|
||||
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void rl_ttyset(int Reset)
|
||||
{
|
||||
static struct termios old;
|
||||
struct termios new;
|
||||
|
||||
if (!Reset) {
|
||||
if (-1 == tcgetattr(0, &old))
|
||||
perror("Failed tcgetattr");
|
||||
if (-1 == getattr(0, &old))
|
||||
perror("Failed tcgetattr()");
|
||||
rl_erase = old.c_cc[VERASE];
|
||||
rl_kill = old.c_cc[VKILL];
|
||||
rl_eof = old.c_cc[VEOF];
|
||||
@ -50,11 +105,11 @@ void rl_ttyset(int Reset)
|
||||
new.c_iflag &= ~ISTRIP;
|
||||
new.c_cc[VMIN] = 1;
|
||||
new.c_cc[VTIME] = 0;
|
||||
if (-1 == tcsetattr(0, TCSADRAIN, &new))
|
||||
perror("Failed tcsetattr");
|
||||
if (-1 == setattr(0, TCSADRAIN, &new))
|
||||
perror("Failed tcsetattr(TCSADRAIN)");
|
||||
} else {
|
||||
if (-1 == tcsetattr(0, TCSADRAIN, &old))
|
||||
perror("Failed tcsetattr");
|
||||
if (-1 == setattr(0, TCSADRAIN, &old))
|
||||
perror("Failed tcsetattr(TCSADRAIN)");
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +122,7 @@ void rl_ttyset(int Reset)
|
||||
struct termio new;
|
||||
|
||||
if (!Reset) {
|
||||
if (-1 == ioctl(0, TCGETA, &old))
|
||||
if (-1 == ioctl_wrap(0, TCGETA, &old))
|
||||
perror("Failed ioctl(TCGETA)");
|
||||
rl_erase = old.c_cc[VERASE];
|
||||
rl_kill = old.c_cc[VKILL];
|
||||
@ -88,10 +143,10 @@ void rl_ttyset(int Reset)
|
||||
|
||||
new.c_cc[VMIN] = 1;
|
||||
new.c_cc[VTIME] = 0;
|
||||
if (-1 == ioctl(0, TCSETAW, &new))
|
||||
if (-1 == ioctl_wrap(0, TCSETAW, &new))
|
||||
perror("Failed ioctl(TCSETAW)");
|
||||
} else {
|
||||
if (-1 == ioctl(0, TCSETAW, &old))
|
||||
if (-1 == ioctl_wrap(0, TCSETAW, &old))
|
||||
perror("Failed ioctl(TCSETAW)");
|
||||
}
|
||||
}
|
||||
@ -110,19 +165,19 @@ void rl_ttyset(int Reset)
|
||||
#endif
|
||||
|
||||
if (!Reset) {
|
||||
if (-1 == ioctl(0, TIOCGETP, &old_sgttyb))
|
||||
if (-1 == ioctl_wrap(0, TIOCGETP, &old_sgttyb))
|
||||
perror("Failed TIOCGETP");
|
||||
rl_erase = old_sgttyb.sg_erase;
|
||||
rl_kill = old_sgttyb.sg_kill;
|
||||
|
||||
if (-1 == ioctl(0, TIOCGETC, &old_tchars))
|
||||
if (-1 == ioctl_wrap(0, TIOCGETC, &old_tchars))
|
||||
perror("Failed TIOCGETC");
|
||||
rl_eof = old_tchars.t_eofc;
|
||||
rl_intr = old_tchars.t_intrc;
|
||||
rl_quit = old_tchars.t_quitc;
|
||||
|
||||
#ifdef CONFIG_SIGSTOP
|
||||
if (-1 == ioctl(0, TIOCGLTC, &old_ltchars))
|
||||
if (-1 == ioctl_wrap(0, TIOCGLTC, &old_ltchars))
|
||||
perror("Failed TIOCGLTC");
|
||||
rl_susp = old_ltchars.t_suspc;
|
||||
#endif
|
||||
@ -134,17 +189,17 @@ void rl_ttyset(int Reset)
|
||||
new_sgttyb.sg_flags &= ~PASS8;
|
||||
else
|
||||
new_sgttyb.sg_flags |= PASS8;
|
||||
if (-1 == ioctl(0, TIOCSETP, &new_sgttyb))
|
||||
if (-1 == ioctl_wrap(0, TIOCSETP, &new_sgttyb))
|
||||
perror("Failed TIOCSETP");
|
||||
new_tchars = old_tchars;
|
||||
new_tchars.t_intrc = -1;
|
||||
new_tchars.t_quitc = -1;
|
||||
if (-1 == ioctl(0, TIOCSETC, &new_tchars))
|
||||
if (-1 == ioctl_wrap(0, TIOCSETC, &new_tchars))
|
||||
perror("Failed TIOCSETC");
|
||||
} else {
|
||||
if (-1 == ioctl(0, TIOCSETP, &old_sgttyb))
|
||||
if (-1 == ioctl_wrap(0, TIOCSETP, &old_sgttyb))
|
||||
perror("Failed TIOCSETP");
|
||||
if (-1 == ioctl(0, TIOCSETC, &old_tchars))
|
||||
if (-1 == ioctl_wrap(0, TIOCSETC, &old_tchars))
|
||||
perror("Failed TIOCSETC");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user