X-Git-Url: https://git.xandkar.net/?a=blobdiff_plain;f=x5%2Fkhatus.c;h=62b3774fdb21c18604dfd4da7de1e11f8b1fe926;hb=80e23f5474b94b36f66c0406425f2214d89eaf6e;hp=4c8a6656fa8f702c15b5cefe81f1ee7f8120f606;hpb=8ce5d971312e8bb27817e359e9712b3edfe011b5;p=khatus.git diff --git a/x5/khatus.c b/x5/khatus.c index 4c8a665..62b3774 100644 --- a/x5/khatus.c +++ b/x5/khatus.c @@ -328,15 +328,11 @@ fifo_read_error(Fifo *f, char *buf) enum read_status fifo_read_one(Fifo *f, char *buf) { - /* Initialize all to an impossible value: */ - ssize_t n = -5; /* Number of bytes read. */ - char c = -1; /* Character read. */ - int r = -1; /* Remaining unused slots in buffer range. */ + char c; /* Character read. */ + int r; /* Remaining unused slots in buffer range. */ for (;;) { - n = read(f->fd, &c, 1); - assert(n >= -1 && n <= 1); - switch (n) { + switch (read(f->fd, &c, 1)) { case -1: error("Failed to read: \"%s\". errno: %d, msg: %s\n", f->name, errno, strerror(errno)); @@ -377,7 +373,7 @@ fifo_read_all(Config *cfg, char *buf) { fd_set fds; int maxfd = -1; - int ready; + int ready = 0; struct stat st; FD_ZERO(&fds); @@ -415,24 +411,43 @@ fifo_read_all(Config *cfg, char *buf) debug("ready: %d\n", ready); assert(ready != 0); if (ready < 0) + /* TODO: Do we really want to fail here? */ fatal("%s", strerror(errno)); - for (Fifo *f = cfg->fifos; f; f = f->next) { - if (FD_ISSET(f->fd, &fds)) { - debug("reading: %s\n", f->name); - switch (fifo_read_one(f, buf)) { - case END_OF_FILE: - case FAILURE: - close(f->fd); - f->fd = -1; - break; - case END_OF_MESSAGE: - case RETRY: - break; - default: - assert(0); + while (ready) { + for (Fifo *f = cfg->fifos; f; f = f->next) { + if (FD_ISSET(f->fd, &fds)) { + debug("reading: %s\n", f->name); + switch (fifo_read_one(f, buf)) { + /* + * ### MESSAGE LOSS ### + * is introduced by closing at EOM in addition + * to EOF, since there may be unread messages + * remaining in the pipe. However, + * + * ### INTER-MESSAGE PUSHBACK ### + * is also gained, since pipes block at the + * "open" call. + * + * This is an acceptable trade-off because we + * are a stateless reporter of a _most-recent_ + * status, not a stateful accumulator. + */ + case END_OF_MESSAGE: + case END_OF_FILE: + case FAILURE: + close(f->fd); + f->fd = -1; + ready--; + break; + case RETRY: + break; + default: + assert(0); + } } } } + assert(ready == 0); } int