From 1b8234e3425e518f40e00751cd0e5261649c166e Mon Sep 17 00:00:00 2001 From: Paul LeoNerd Evans Date: Thu, 25 Aug 2011 10:48:41 +0100 Subject: [PATCH] Provide a flag to return RES_ERROR even on signal (EINTR); without it, retry the operation --- termkey.c | 14 ++++++++++++-- termkey.h.in | 3 ++- termkey_advisereadable.3 | 2 +- termkey_new.3 | 3 +++ termkey_waitkey.3.sh | 2 +- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/termkey.c b/termkey.c index dd1020b..921bb6c 100644 --- a/termkey.c +++ b/termkey.c @@ -841,12 +841,17 @@ TermKeyResult termkey_waitkey(TermKey *tk, TermKeyKey *key) struct pollfd fd; +retry: fd.fd = tk->fd; fd.events = POLLIN; int pollret = poll(&fd, 1, tk->waittime); - if(pollret == -1) + if(pollret == -1) { + if(errno == EINTR && !(tk->flags & TERMKEY_FLAG_EINTR)) + goto retry; + return TERMKEY_RES_ERROR; + } if(fd.revents & (POLLIN|POLLHUP|POLLERR)) ret = termkey_advisereadable(tk); @@ -884,11 +889,16 @@ void termkey_pushinput(TermKey *tk, const unsigned char *input, size_t inputlen) TermKeyResult termkey_advisereadable(TermKey *tk) { unsigned char buffer[64]; // Smaller than the default size - ssize_t len = read(tk->fd, buffer, sizeof buffer); + ssize_t len; + +retry: + len = read(tk->fd, buffer, sizeof buffer); if(len == -1) { if(errno == EAGAIN) return TERMKEY_RES_NONE; + else if(errno == EINTR && !(tk->flags & TERMKEY_FLAG_EINTR)) + goto retry; else return TERMKEY_RES_ERROR; } diff --git a/termkey.h.in b/termkey.h.in index 33360d8..a22ce5f 100644 --- a/termkey.h.in +++ b/termkey.h.in @@ -145,7 +145,8 @@ enum { TERMKEY_FLAG_UTF8 = 1 << 3, // Input is definitely UTF-8 TERMKEY_FLAG_NOTERMIOS = 1 << 4, // Do not make initial termios calls on construction TERMKEY_FLAG_SPACESYMBOL = 1 << 5, // Space is symbolic rather than Unicode - TERMKEY_FLAG_CTRLC = 1 << 6 // Allow Ctrl-C to be read as normal, disabling SIGINT + TERMKEY_FLAG_CTRLC = 1 << 6, // Allow Ctrl-C to be read as normal, disabling SIGINT + TERMKEY_FLAG_EINTR = 1 << 7 // Return ERROR on signal (EINTR) rather than retry }; void termkey_check_version(int major, int minor); diff --git a/termkey_advisereadable.3 b/termkey_advisereadable.3 index ba859ca..fe70125 100644 --- a/termkey_advisereadable.3 +++ b/termkey_advisereadable.3 @@ -25,7 +25,7 @@ At least one byte was read. No nore bytes were read. .TP .B TERMKEY_RES_ERROR -An IO error occured. \fIerrno\fP will be preserved. +An IO error occured. \fIerrno\fP will be preserved. If the error is \fBEINTR\fP then this will only be returned if \fBTERMKEY_FLAG_EINTR\fP flag is not set; if it is then the IO operation will be retried instead. .SH "SEE ALSO" .BR termkey_new (3), .BR termkey_getkey (3), diff --git a/termkey_new.3 b/termkey_new.3 index 3cb24ce..7cf307a 100644 --- a/termkey_new.3 +++ b/termkey_new.3 @@ -42,6 +42,9 @@ Report space as being a symbolic key rather than a Unicode codepoint. .TP .B TERMKEY_FLAG_CTRLC Disable the \fBSIGINT\fP behaviour of \fICtrl-C\fP. If this flag is provided, then \fICtrl-C\fP will be available as a normal keypress, rather than sending the process group a \fBSIGINT\fP. This flag only takes effect without \fBTERMKEY_FLAG_NOTERMIOS\fP; with it, none of the signal keys are disabled anyway. +.TP +.B TERMKEY_FLAG_EINTR +Without this flag, IO operations are retried when interrupted by a signal (\fBEINTR\fP). With this flag the \fBTERMKEY_RES_ERROR\fP result is returned instead. .PP When the constructor is invoked, it attempts to detect if the current locale is UTF-8 aware or not, and sets either the \fBTERMKEY_FLAG_UTF8\fP or \fBTERMKEY_FLAG_RAW\fP flag. One of these two bits will always be in effect. The current flags in effect can be obtained by \fBtermkey_get_flags\fP(3). .SH VERSION CHECK MACRO diff --git a/termkey_waitkey.3.sh b/termkey_waitkey.3.sh index 81d9f6e..ee8edaf 100644 --- a/termkey_waitkey.3.sh +++ b/termkey_waitkey.3.sh @@ -27,7 +27,7 @@ A key event as been provided. No key events are ready and the terminal has been closed, so no more will arrive. .TP .B TERMKEY_RES_ERROR -An IO error occured. \fIerrno\fP will be preserved. +An IO error occured. \fIerrno\fP will be preserved. If the error is \fBEINTR\fP then this will only be returned if \fBTERMKEY_FLAG_EINTR\fP flag is not set; if it is then the IO operation will be retried instead. .SH EXAMPLE The following example program prints details of every keypress until the user presses "Ctrl-C". .PP