switch writen() to blocking_write() to avoid spinning

pull/1755/head
nick black 3 years ago
parent 3622a96d29
commit 5912a2138a
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -38,7 +38,7 @@ int ncdirect_putstr(ncdirect* nc, uint64_t channels, const char* utf8){
static int
cursor_yx_get(int ttyfd, int* y, int* x){
if(writen(ttyfd, "\033[6n", 4) != 4){
if(blocking_write(ttyfd, "\033[6n", 4)){
return -1;
}
bool done = false;

@ -8,6 +8,7 @@ extern "C" {
#include "version.h"
#include "builddef.h"
#include <poll.h>
#include <term.h>
#include <time.h>
#include <stdio.h>
@ -741,21 +742,31 @@ rgb_greyscale(int r, int g, int b){
return fg * 255;
}
// write(2) with retry on partial write or interrupted write
static inline ssize_t
writen(int fd, const void* buf, size_t len){
ssize_t r;
size_t w = 0;
while(w < len){
if((r = write(fd, (const char*)buf + w, len - w)) < 0){
if(errno == EAGAIN || errno == EBUSY || errno == EINTR){
continue;
// 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){
return -1;
}
return -1;
}else{
written += w;
}
if(written < buflen){
struct pollfd pfd = {
.fd = fd,
.events = POLLOUT,
.revents = 0,
};
poll(&pfd, 1, -1);
}
w += r;
}
return w;
return 0;
}
static inline int
@ -764,7 +775,7 @@ tty_emit(const char* seq, int fd){
return -1;
}
size_t slen = strlen(seq);
if(writen(fd, seq, slen) < 0){
if(blocking_write(fd, seq, slen)){
return -1;
}
return 0;

@ -1,4 +1,3 @@
#include <poll.h>
#include <ctype.h>
#include <limits.h>
#include <unistd.h>
@ -74,33 +73,6 @@ notcurses_resize(notcurses* n, int* restrict rows, int* restrict cols){
return ret;
}
// write(2) until we've written it all. Uses poll(2) to avoid spinning on
// EAGAIN, at a small cost of latency.
static 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){
return -1;
}
}else{
written += w;
}
if(written < buflen){
struct pollfd pfd = {
.fd = fd,
.events = POLLOUT,
.revents = 0,
};
poll(&pfd, 1, -1);
}
}
return 0;
}
void nccell_release(ncplane* n, nccell* c){
pool_release(&n->pool, c);
}

@ -458,8 +458,7 @@ read_xtsmgraphics_reply(int fd, int* val2){
static int
query_xtsmgraphics(int fd, const char* seq, int* val, int* val2){
ssize_t w = writen(fd, seq, strlen(seq));
if(w < 0 || (size_t)w != strlen(seq)){
if(blocking_write(fd, seq, strlen(seq))){
return -1;
}
int r = read_xtsmgraphics_reply(fd, val2);

Loading…
Cancel
Save