fbuf_{flush,finalize}(): don't use unreliable stdio

pull/2048/head
nick black 3 years ago
parent 3cb54dec83
commit c5b0ba4dd0
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -14,6 +14,5 @@ void notcurses_debug(const notcurses* nc, FILE* debugfp){
return;
}
notcurses_debug_fbuf(nc, &f);
fbuf_finalize(&f, debugfp, true);
fbuf_free(&f);
fbuf_finalize(&f, debugfp);
}

@ -524,7 +524,7 @@ ncdirect_dump_plane(ncdirect* n, const ncplane* np, int xoff){
fbuf_free(&f);
return -1;
}
if(fbuf_finalize(&f, n->ttyfp, true)){
if(fbuf_finalize(&f, n->ttyfp)){
return -1;
}
return 0;
@ -973,7 +973,7 @@ int ncdirect_on_styles(ncdirect* n, unsigned stylebits){
fbuf_free(&f);
return -1;
}
if(fbuf_finalize(&f, n->ttyfp, false)){
if(fbuf_finalize(&f, n->ttyfp)){
return -1;
}
return 0;
@ -998,7 +998,7 @@ int ncdirect_off_styles(ncdirect* n, unsigned stylebits){
fbuf_free(&f);
return -1;
}
if(fbuf_finalize(&f, n->ttyfp, false)){
if(fbuf_finalize(&f, n->ttyfp)){
return -1;
}
return 0;
@ -1022,7 +1022,7 @@ int ncdirect_set_styles(ncdirect* n, unsigned stylebits){
fbuf_free(&f);
return -1;
}
if(fbuf_finalize(&f, n->ttyfp, false)){
if(fbuf_finalize(&f, n->ttyfp)){
return -1;
}
return 0;

@ -9,8 +9,10 @@ extern "C" {
#include <assert.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <inttypes.h>
#include "compat/compat.h"
#include "logging.h"
// a growable buffer into which one can perform formatted i/o, like the
// ten thousand that came before it, and the ten trillion which shall
@ -243,36 +245,61 @@ fbuf_free(fbuf* f){
}
}
// write(2) until we've written it all. uses poll(2) to avoid spinning on
// EAGAIN, at the possible cost of some small latency.
static inline int
blocking_write(int fd, const char* buf, size_t buflen){
//fprintf(stderr, "writing %zu to %d...\n", buflen, fd);
size_t written = 0;
while(written < buflen){
ssize_t w = write(fd, buf + written, buflen - written);
if(w < 0){
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR && errno != EBUSY){
logerror("Error writing out data on %d (%s)\n", fd, strerror(errno));
return -1;
}
}else{
written += w;
}
// FIXME ought probably use WSAPoll() on windows
#ifndef __MINGW64__
if(written < buflen){
struct pollfd pfd = {
.fd = fd,
.events = POLLOUT,
.revents = 0,
};
poll(&pfd, 1, -1);
}
#endif
}
return 0;
}
// attempt to write the contents of |f| to the FILE |fp|, if there are any
// contents. reset the fbuf either way. if |flushfp| is set, fflush(fp).
// contents. reset the fbuf either way.
static inline int
fbuf_flush(fbuf* f, FILE* fp, bool flushfp){
fbuf_flush(fbuf* f, FILE* fp){
int ret = 0;
if(f->used){
if(fwrite(f->buf, f->used, 1, fp) != 1){
if(blocking_write(fileno(fp), f->buf, f->used)){
ret = -1;
}
}
if(flushfp && ret == 0 && fflush(fp) == EOF){
ret = -1;
}
fbuf_reset(f);
return ret;
}
// attempt to write the contents of |f| to the FILE |fp|, if there are any
// contents, and free the fbuf either way. if |flushfp| is set, fflush(fp).
// contents, and free the fbuf either way.
static inline int
fbuf_finalize(fbuf* f, FILE* fp, bool flushfp){
fbuf_finalize(fbuf* f, FILE* fp){
int ret = 0;
if(f->used){
if(fwrite(f->buf, f->used, 1, fp) != 1){
if(blocking_write(fileno(fp), f->buf, f->used)){
ret = -1;
}
}
if(flushfp && ret == 0 && fflush(fp) == EOF){
ret = -1;
}
fbuf_free(f);
return ret;
}

@ -1059,37 +1059,6 @@ int ncvisual_blit(struct ncvisual* ncv, int rows, int cols,
ncplane* n, const struct blitset* bset,
const blitterargs* bargs);
// write(2) until we've written it all. uses poll(2) to avoid spinning on
// EAGAIN, at the possible cost of some small latency.
static inline int
blocking_write(int fd, const char* buf, size_t buflen){
//fprintf(stderr, "writing %zu to %d...\n", buflen, fd);
size_t written = 0;
while(written < buflen){
ssize_t w = write(fd, buf + written, buflen - written);
if(w < 0){
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR){
logerror("Error writing out data on %d (%s)\n", fd, strerror(errno));
return -1;
}
}else{
written += w;
}
// FIXME ought use WSAPoll() on windows
#ifndef __MINGW64__
if(written < buflen){
struct pollfd pfd = {
.fd = fd,
.events = POLLOUT,
.revents = 0,
};
poll(&pfd, 1, -1);
}
#endif
}
return 0;
}
static inline int
tty_emit(const char* seq, int fd){
if(!seq){

@ -1289,7 +1289,7 @@ int notcurses_stop(notcurses* nc){
}
fbuf_reset(&nc->rstate.f);
goto_location(nc, &nc->rstate.f, targy, 0);
fbuf_finalize(&nc->rstate.f, stdout, true);
fbuf_finalize(&nc->rstate.f, stdout);
}
ret |= set_fd_nonblocking(nc->tcache.input.infd, nc->stdio_blocking_save, NULL);
if(nc->stdplane){

@ -1244,7 +1244,7 @@ notcurses_rasterize(notcurses* nc, ncpile* p, fbuf* f){
notcurses_cursor_enable(nc, cursory, cursorx);
}else if(nc->rstate.logendy >= 0){
goto_location(nc, f, nc->rstate.logendy, nc->rstate.logendx);
if(fbuf_flush(f, nc->ttyfp, true)){
if(fbuf_flush(f, nc->ttyfp)){
ret = -1;
}
}
@ -1449,14 +1449,14 @@ int ncpile_render(ncplane* n){
}
int notcurses_render(notcurses* nc){
//fprintf(stderr, "--------------- BEGIN RENDER %d/%d\n", nc->rstate.y, nc->rstate.x);
//fprintf(stderr, "--------------- BEGIN RENDER\n");
//notcurses_debug(nc, stderr);
ncplane* stdn = notcurses_stdplane(nc);
if(ncpile_render(stdn)){
return -1;
}
int i = ncpile_rasterize(stdn);
//fprintf(stderr, "----------------- END RENDER %d/%d\n", nc->rstate.y, nc->rstate.x);
//fprintf(stderr, "----------------- END RENDER\n");
return i;
}
@ -1600,7 +1600,7 @@ int notcurses_cursor_enable(notcurses* nc, int y, int x){
fbuf_free(&f);
return -1;
}
if(fbuf_finalize(&f, nc->ttyfp, true)){
if(fbuf_finalize(&f, nc->ttyfp)){
return -1;
}
// if we were already positive, we're already visible, no need to write cnorm

Loading…
Cancel
Save