Use Windows pipes for input readiness notification (#2263)

* [windows] use CreatePipe for input #2244
* [input] read and write to Windows readiness handles #2244
* inputready_fd: not on windows, alas
pull/2274/head
nick black 3 years ago committed by GitHub
parent abea3f9064
commit 245f9f85c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -23,7 +23,6 @@
// redirected from a file (NCOPTION_TOSS_INPUT) // redirected from a file (NCOPTION_TOSS_INPUT)
// FIXME still need to: // FIXME still need to:
// integrate main specials trie with automaton, enable input_errors
// probably want pipes/eventfds rather than SIGCONT // probably want pipes/eventfds rather than SIGCONT
static sig_atomic_t resize_seen; static sig_atomic_t resize_seen;
@ -50,6 +49,12 @@ typedef struct cursorloc {
int y, x; // 0-indexed cursor location int y, x; // 0-indexed cursor location
} cursorloc; } cursorloc;
#ifndef __MINGW64__
typedef int ipipe;
#else
typedef PHANDLE ipipe;
#endif
// local state for the input thread. don't put this large struct on the stack. // local state for the input thread. don't put this large struct on the stack.
typedef struct inputctx { typedef struct inputctx {
int stdinfd; // bulk in fd. always >= 0 (almost always 0). we do not int stdinfd; // bulk in fd. always >= 0 (almost always 0). we do not
@ -100,7 +105,7 @@ typedef struct inputctx {
unsigned drain; // drain away bulk input? unsigned drain; // drain away bulk input?
ncsharedstats *stats; // stats shared with notcurses context ncsharedstats *stats; // stats shared with notcurses context
int readypipes[2]; // pipes[0]: poll()able fd indicating the presence of user input ipipe readypipes[2]; // pipes[0]: poll()able fd indicating the presence of user input
struct initial_responses* initdata; struct initial_responses* initdata;
struct initial_responses* initdata_complete; struct initial_responses* initdata_complete;
} inputctx; } inputctx;
@ -438,10 +443,16 @@ send_synth_signal(int sig){
} }
static void static void
mark_pipe_ready(int pipes[static 2]){ mark_pipe_ready(ipipe pipes[static 2]){
char sig = 1; char sig = 1;
#ifndef __MINGW64__
if(write(pipes[1], &sig, sizeof(sig)) != 1){ if(write(pipes[1], &sig, sizeof(sig)) != 1){
logwarn("error writing to readypipe (%d) (%s)\n", pipes[1], strerror(errno)); logwarn("error writing to readypipe (%d) (%s)\n", pipes[1], strerror(errno));
#else
DWORD wrote;
if(!WriteFile(pipes[1], &sig, sizeof(sig), &wrote, NULL) || wrote != sizeof(sig)){
logwarn("error writing to readypipe\n");
#endif
} }
} }
@ -1321,18 +1332,27 @@ build_cflow_automaton(inputctx* ictx){
} }
static void static void
endpipes(int pipes[static 2]){ closepipe(ipipe p){
if(pipes[0] >= 0){ #ifndef __MINGW64__
close(pipes[0]); if(p >= 0){
close(p);
} }
if(pipes[1] >= 0){ #else
close(pipes[1]); if(p){
CloseHandle(p);
} }
#endif
}
static void
endpipes(ipipe pipes[static 2]){
closepipe(pipes[0]);
closepipe(pipes[1]);
} }
// only linux and freebsd13+ have eventfd(), so we'll fall back to pipes sigh. // only linux and freebsd13+ have eventfd(), so we'll fall back to pipes sigh.
static int static int
getpipes(int pipes[static 2]){ getpipes(ipipe pipes[static 2]){
#ifndef __MINGW64__ #ifndef __MINGW64__
#ifndef __APPLE__ #ifndef __APPLE__
if(pipe2(pipes, O_CLOEXEC | O_NONBLOCK)){ if(pipe2(pipes, O_CLOEXEC | O_NONBLOCK)){
@ -1345,19 +1365,21 @@ getpipes(int pipes[static 2]){
return -1; return -1;
} }
if(set_fd_cloexec(pipes[0], 1, NULL) || set_fd_nonblocking(pipes[0], 1, NULL)){ if(set_fd_cloexec(pipes[0], 1, NULL) || set_fd_nonblocking(pipes[0], 1, NULL)){
logerror("couldn't prep pipe[0] (%d) (%s)\n", pipes[0], strerror(errno)); logerror("couldn't prep pipe[0] (%s)\n", strerror(errno));
endpipes(pipes); endpipes(pipes);
return -1; return -1;
} }
if(set_fd_cloexec(pipes[1], 1, NULL) || set_fd_nonblocking(pipes[1], 1, NULL)){ if(set_fd_cloexec(pipes[1], 1, NULL) || set_fd_nonblocking(pipes[1], 1, NULL)){
logerror("couldn't prep pipe[1] (%d) (%s)\n", pipes[1], strerror(errno)); logerror("couldn't prep pipe[1] (%s)\n", strerror(errno));
endpipes(pipes); endpipes(pipes);
return -1; return -1;
} }
// FIXME what to do on windows?
#endif #endif
#else // windows #else // windows
pipes[0] = pipes[1] = -1; if(!CreatePipe(&pipes[0], &pipes[1], NULL, BUFSIZ)){
logerror("couldn't get pipes (%u)\n", GetLastError());
return -1;
}
#endif #endif
return 0; return 0;
} }
@ -2026,7 +2048,13 @@ int stop_inputlayer(tinfo* ti){
} }
int inputready_fd(const inputctx* ictx){ int inputready_fd(const inputctx* ictx){
#ifndef __MINGW64__
return ictx->readypipes[0]; return ictx->readypipes[0];
#else
(void)ictx;
logerror("readiness descriptor unavailable on windows\n");
return -1;
#endif
} }
static inline uint32_t static inline uint32_t
@ -2073,9 +2101,15 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){
}else if(ictx->ivalid){ }else if(ictx->ivalid){
logtrace("draining event readiness pipe\n"); logtrace("draining event readiness pipe\n");
char c; char c;
#ifndef __MINGW64__
while(read(ictx->readypipes[0], &c, sizeof(c)) == 1){ while(read(ictx->readypipes[0], &c, sizeof(c)) == 1){
// FIXME accelerate; // FIXME accelerate?
} }
#else
while(ReadFile(ictx->readypipes[0], &c, sizeof(c), NULL, NULL)){
// FIXME accelerate?
}
#endif
} }
pthread_mutex_unlock(&ictx->ilock); pthread_mutex_unlock(&ictx->ilock);
if(sendsignal){ if(sendsignal){

Loading…
Cancel
Save