commit 3bf4efd89a43d94ad46bdda31137a3bc9404ed8c
parent 32e1b3714fc4c84188673f668fca121b7c9e9256
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Fri, 24 Oct 2014 21:35:06 +0000
rework read/write fd code, sleep when there are too much timeouts
Diffstat:
M | sob.c | | | 114 | +++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
1 file changed, 76 insertions(+), 38 deletions(-)
diff --git a/sob.c b/sob.c
@@ -11,6 +11,7 @@
#include <sys/select.h>
#include <unistd.h>
#include <termios.h>
+#include <time.h>
#include <wchar.h>
#include "arg.h"
@@ -60,8 +61,8 @@ static int line_promptlen(void);
static int line_pipeto(char **);
static int line_wordpipeto(char **);
-static int pipe_readline(int, int, char *,
- void (*)(const char *, size_t, size_t));
+static int pipe_read(int, int, char *,
+ void (*)(const char *, size_t, size_t));
static int pipe_cmd(char *[], char *,
void (*)(const char *, size_t, size_t));
@@ -75,6 +76,9 @@ static void setup(void);
static void sighandler(int);
static void usage(void);
+static int readfd(int, char *, size_t);
+static int writefd(int, char *, size_t);
+
static size_t colw(const char *, size_t);
static int nonspace(int c);
static size_t utf8len(const char *);
@@ -547,7 +551,47 @@ line_copywordcursor(char *buf, size_t bufsiz)
}
static int
-pipe_readline(int fd_in, int fd_out, char *writestr,
+readfd(int fd, char *buf, size_t len) {
+ size_t r, i = 0;
+
+ while(len > 0) {
+ if((r = read(fd, &buf[i], len)) == -1) {
+ if(errno == EINTR)
+ continue;
+ if(errno == EWOULDBLOCK)
+ return i;
+ return -1;
+ } else if(r == 0) {
+ return i;
+ }
+ i += r;
+ len -= r;
+ }
+ return i;
+}
+
+static int
+writefd(int fd, char *buf, size_t len) {
+ size_t w, i = 0;
+
+ while(len > 0) {
+ if((w = write(fd, &buf[i], len)) == -1) {
+ if(errno == EINTR)
+ continue;
+ if(errno == EWOULDBLOCK)
+ return i;
+ return -1;
+ } else if(w == 0) {
+ return i;
+ }
+ i += w;
+ len -= w;
+ }
+ return i;
+}
+
+static int
+pipe_read(int fd_in, int fd_out, char *writestr,
void (*f)(const char *, size_t, size_t))
{
char buf[PIPE_BUF];
@@ -576,35 +620,28 @@ pipe_readline(int fd_in, int fd_out, char *writestr,
else if(!r) /* timeout */
continue;
- if(haswritten) {
- if(FD_ISSET(fd_in, &fdr)) {
- while(1) {
- if((r = read(fd_in, buf, sizeof(buf))) == -1) {
- if(errno == EINTR)
- continue;
- goto fini;
- } else {
- buf[r] = '\0';
- total += r;
- if(f)
- f(buf, r, total);
- if(!r) {
- status = 0;
- goto fini;
- }
- }
- }
- }
- } else {
- if(FD_ISSET(fd_out, &fdw)) {
- /* write error */
- if((w = write(fd_out, writestr, strlen(writestr))) == -1)
+ if(FD_ISSET(fd_in, &fdr) && haswritten) {
+ while(1) {
+ if((r = readfd(fd_in, buf, sizeof(buf))) <= 0)
goto fini;
- close(fd_out); /* sends EOF */
- fd_out = -1;
- haswritten = 1;
+ if(!r) {
+ status = 0;
+ goto fini;
+ }
+ if(f) {
+ buf[r] = '\0';
+ total += r;
+ f(buf, r, total);
+ }
}
}
+ if(FD_ISSET(fd_out, &fdw)) {
+ if((w = writefd(fd_out, writestr, strlen(writestr))) == -1)
+ goto fini;
+ close(fd_out); /* sends EOF */
+ fd_out = -1;
+ haswritten = 1;
+ }
}
fini:
if(fd_in != -1)
@@ -656,7 +693,7 @@ pipe_cmd(char *cmd[], char *writestr, void (*f)(const char *, size_t, size_t))
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sa, NULL);
- if(pipe_readline(cp[0], pc[1], writestr, f) == -1)
+ if(pipe_read(cp[0], pc[1], writestr, f) == -1)
return -1;
}
return 0;
@@ -812,6 +849,7 @@ static int
run(void)
{
struct timeval tv;
+ struct timespec ts;
fd_set fdr;
int r, status = -1;
unsigned char buf[BUFSIZ];
@@ -828,22 +866,22 @@ run(void)
tv.tv_sec = 0;
tv.tv_usec = 32000; /* 32 ms */
- errno = 0;
if((r = select(STDIN_FILENO + 1, &fdr, NULL, NULL, &tv)) == -1) {
if(errno != EINTR)
- goto fini; /* E_INTR can happen on SIGWINCH */
+ goto fini; /* E_INTR can happen on a signal like SIGWINCH */
} else if(!r) {
continue; /* timeout */
}
-
if(FD_ISSET(STDIN_FILENO, &fdr)) {
- errno = 0;
- if((r = read(STDIN_FILENO, buf, sizeof(buf))) == -1) {
- if(errno != EAGAIN && errno != EWOULDBLOCK)
- goto fini;
- } else if(r > 0) {
+ if((r = readfd(STDIN_FILENO, (char *)buf, sizeof(buf))) == -1)
+ goto fini;
+ if(r > 0) {
buf[r] = '\0';
handleinput(buf, r);
+ } else if(r == 0) {
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+ nanosleep(&ts, NULL);
}
}
}