From ac7389ad62c296bf0a7dfd8adb8ec5f515b0abe7 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Wed, 21 Mar 2018 22:12:52 -0400 Subject: [PATCH] starting combining job control and fd monitoring --- Makefile | 3 +- inc/edit.h | 25 ++++--- lib/event.c | 67 ----------------- lib/exec.c | 202 ++++++---------------------------------------------- lib/win.c | 6 +- lib/x11.c | 2 +- tide.c | 20 ++---- 7 files changed, 45 insertions(+), 280 deletions(-) delete mode 100644 lib/event.c diff --git a/Makefile b/Makefile index 00ecd47..231abe7 100644 --- a/Makefile +++ b/Makefile @@ -13,8 +13,7 @@ LIBEDIT_OBJS = \ lib/x11.o \ lib/win.o \ lib/colors.o \ - lib/config.o \ - lib/event.o + lib/config.o TEST_BINS = \ tests/tide \ diff --git a/inc/edit.h b/inc/edit.h index ed5d143..98d41cc 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -22,15 +22,6 @@ bool file_exists(char* path); char* strmcat(char* first, ...); int daemonize(void); -/* File Descriptor Event Handling - *****************************************************************************/ -enum { INPUT, OUTPUT }; - -typedef void (*event_cbfn_t)(int fd, void* data); - -bool event_poll(int ms); -void event_watchfd(int fd, int iodir, event_cbfn_t fn, void* data); - /* Buffer management functions *****************************************************************************/ /* undo/redo list item */ @@ -222,9 +213,21 @@ Rune view_getrune(View* view); /* Command Executions *****************************************************************************/ -bool exec_reap(void); + +typedef struct Job Job; + +typedef void (*jobfn_t)(Job* job); + +struct Job { + int pid, fd; + void* data; + void (*writefn)(Job* job); + void (*readfn)(Job* job); +}; + +bool exec_poll(int fd, int ms); +int exec_reap(void); void exec_job(char** cmd, char* data, size_t ndata, View* dest); -int exec_cmd(char** cmd); int exec_spawn(char** cmd, int* in, int* out); /* Configuration Data diff --git a/lib/event.c b/lib/event.c deleted file mode 100644 index 284f3ae..0000000 --- a/lib/event.c +++ /dev/null @@ -1,67 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include -#include - -struct event_data { - int iodir; - void* data; - event_cbfn_t fn; -}; - -static size_t NumDescriptors = 0; -static struct pollfd* Descriptors = NULL; -static struct event_data* EventData = NULL; - -bool event_poll(int ms) { - /* poll for new events */ - long n = poll(Descriptors, NumDescriptors, ms); - if (n < 0) die("poll() :"); - if (n == 0) return false; - - /* Handle any events that occurred */ - for (int i = 0; i < NumDescriptors; i++) { - /* skip any eventless entries */ - if (!Descriptors[i].revents) continue; - - /* if a requested event occurred, handle it */ - if (Descriptors[i].revents & Descriptors[i].events) { - EventData[i].fn(Descriptors[i].fd, EventData[i].data); - Descriptors[i].revents = 0; - } - - /* if the desriptor is done or errored, throw it out */ - if (Descriptors[i].revents & (POLLNVAL|POLLERR|POLLHUP)) { - close(Descriptors[i].fd); - Descriptors[i].fd = -Descriptors[i].fd; - EventData[i].fn(Descriptors[i].fd, EventData[i].data); - } - } - - /* remove any closed or invalid descriptors */ - size_t nfds = 0; - for (int i = 0; i < NumDescriptors; i++) { - if (Descriptors[i].fd >= 0) { - Descriptors[nfds] = Descriptors[i]; - EventData[nfds++] = EventData[i]; - } - } - NumDescriptors = nfds; - - return true; -} - -void event_watchfd(int fd, int iodir, event_cbfn_t fn, void* data) { - int idx = NumDescriptors++; - Descriptors = realloc(Descriptors, NumDescriptors * sizeof(struct pollfd)); - EventData = realloc(EventData, NumDescriptors * sizeof(struct event_data)); - if (!Descriptors || !EventData) - die("event_Watchfd() : out of memory\n"); - Descriptors[idx].fd = fd; - Descriptors[idx].revents = 0; - Descriptors[idx].events = (iodir == INPUT ? POLLIN : POLLOUT); - EventData[idx].data = data; - EventData[idx].fn = fn; -} diff --git a/lib/exec.c b/lib/exec.c index 11d2bff..9e7cf16 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -7,205 +7,42 @@ #include #include #include +#include -#define PIPE_READ 0 -#define PIPE_WRITE 1 +#define MAX_JOBS 1024 -typedef struct { - int pid; /* process id of the child process */ - int fd; /* file descriptor for the child process's io */ -} Proc; +static struct pollfd Jobs[MAX_JOBS]; -typedef struct Job Job; - -typedef struct { - Job* job; /* pointer to the job the receiver belongs to */ - View* view; /* destination view */ - size_t beg; /* start of output */ - size_t count; /* number of bytes written */ -} Rcvr; - -struct Job { - Job* next; /* Pointer to previous job in the job list */ - Job* prev; /* Pointer to next job in the job list */ - Proc proc; /* Process id and descriptors */ - size_t ndata; /* number of bytes to write to stdout */ - size_t nwrite; /* number of bytes written to stdout so far */ - char* data; /* data to write to stdout */ - Rcvr out_rcvr; /* receiver for the normal output of the job */ - View* dest; /* destination view where output will be placed */ -}; - -static Job* JobList = NULL; - -static void job_closefd(Job* job, int fd); -static bool job_done(Job* job); -static Job* job_finish(Job* job); -static void send_data(int fd, void* data); -static void recv_data(int fd, void* data); -static int watch_or_close(bool valid, int dir, int fd, void* data); -static void rcvr_finish(Rcvr* rcvr); -static int execute(char** cmd, Proc* proc); - -bool exec_reap(void) { - int status; - Job* job = JobList; - while (job) { - if (job_done(job)) { - rcvr_finish(&(job->out_rcvr)); - waitpid(job->proc.pid, &status, WNOHANG); - job = job_finish(job); - } else { - job = job->next; - } +bool exec_poll(int fd, int ms) { + int njobs = 0; + if (fd > 0) { + Jobs[0].fd = fd; + Jobs[0].events = POLLIN; + Jobs[0].revents = 0; + njobs = 1; } - if (JobList == NULL) - while (waitpid(-1, &status, WNOHANG) > 0); - return (JobList != NULL); -} -void exec_job(char** cmd, char* data, size_t ndata, View* dest) { - Job* job = calloc(1, sizeof(Job)); - job->proc.pid = execute(cmd, &(job->proc)); - if (job->proc.pid < 0) { - die("job_start() :"); - } else { - /* add the job to the job list */ - job->out_rcvr.view = dest; - job->out_rcvr.job = job; - job->ndata = ndata; - job->nwrite = 0; - job->data = data; - job->next = JobList; - if (JobList) JobList->prev = job; - JobList = job; - /* register watch events for file descriptors */ - bool need_in = (job->data != NULL), - need_out = (dest != NULL); - watch_or_close(need_in, OUTPUT, job->proc.fd, job); - watch_or_close(need_out, INPUT, job->proc.fd, &(job->out_rcvr)); + long ret = poll(Jobs, njobs, ms); -/* - event_cbfn_t fn = (dir == OUTPUT ? send_data : recv_data); - if (valid) - event_watchfd(fd, dir, fn, data); - else - close(fd), fd = -fd; -*/ + /* reap zombie processes */ + for (int status; waitpid(-1, &status, WNOHANG) > 0;); - } + return (ret > 0); } -int exec_cmd(char** cmd) { - Proc proc; - if (execute(cmd, &proc) < 0) { - perror("failed to execute"); - return -1; - } - /* wait for the process to finish */ - int status; - waitpid(proc.pid, &status, 0); - return status; +int exec_reap(void) { + return 0; } int exec_spawn(char** cmd, int* in, int* out) { - Proc proc; - if (execute(cmd, &proc) < 0) { - perror("failed to execute"); - return -1; - } - *in = proc.fd; - *out = proc.fd; - return proc.pid; -} - -static void job_closefd(Job* job, int fd) { - if (fd >= 0) close(fd), fd = -fd; - if (job->proc.fd == -fd) job->proc.fd = fd; -} - -static bool job_done(Job* job) { - return (job->proc.fd < 0); + return -1; } -static Job* job_finish(Job* job) { - Job* next = job->next; - if (job->prev) { - job->prev->next = next; - if (next) - next->prev = job->prev; - } else { - if (next) - next->prev = NULL; - JobList = next; - } - free(job->data); - free(job); - return next; -} - -static void send_data(int fd, void* data) { - Job* job = data; - if (fd >= 0) { - long nwrite = write(fd, (job->data + job->nwrite), job->ndata); - if (nwrite >= 0) { - job->ndata -= nwrite; - job->nwrite += nwrite; - } - if (nwrite < 0 || job->ndata <= 0) - shutdown(fd, SHUT_WR); - } else { - //event_unwatchfd(job, fd); - } -} - -static void recv_data(int fd, void* data) { - static char buffer[4096]; - Rcvr* rcvr = data; - Job* job = rcvr->job; - View* view = rcvr->view; - Sel sel = view->selection; - - if (fd >= 0) { - long i = 0, nread = read(fd, buffer, sizeof(buffer)); - if (nread > 0) { - if (!rcvr->count) - rcvr->beg = min(sel.beg, sel.end); - while (i < nread) { - Rune r; - size_t len = 0; - while (!utf8decode(&r, &len, buffer[i++])); - view_insert(rcvr->view, false, r); - rcvr->count++; - } - } else { - close(fd); - } - } else { - job_closefd(job, fd); - } -} - -static int watch_or_close(bool valid, int dir, int fd, void* data) { - event_cbfn_t fn = (dir == OUTPUT ? send_data : recv_data); - if (valid) - event_watchfd(fd, dir, fn, data); - else - close(fd), fd = -fd; - return fd; -} +void exec_job(char** cmd, char* data, size_t ndata, View* dest) { -static void rcvr_finish(Rcvr* rcvr) { - if (rcvr->count) { - View* view = rcvr->view; - Buf* buf = &(rcvr->view->buffer); - if (rcvr->view == win_view(TAGS)) - buf_chomp(buf), rcvr->count--; - view->selection.beg = rcvr->beg; - view->selection.end = rcvr->beg + rcvr->count; - } } +#if 0 static int execute(char** cmd, Proc* proc) { int fds[2]; /* create the sockets */ @@ -228,3 +65,4 @@ static int execute(char** cmd, Proc* proc) { } return proc->pid; } +#endif diff --git a/lib/win.c b/lib/win.c index 8b84d20..9e767cf 100644 --- a/lib/win.c +++ b/lib/win.c @@ -97,12 +97,10 @@ void win_save(char* path) { void win_loop(void) { x11_show(); - x11_flip(); - event_watchfd(x11_connfd(), INPUT, win_update, NULL); while (x11_running()) { - bool pending = event_poll(Timeout); + bool pending = exec_poll(x11_connfd(), Timeout); exec_reap(); - int nevents = x11_events_queued(); + int nevents = x11_events_queued(); if (update_focus() || pending || nevents) { x11_events_take(); if (x11_running()) diff --git a/lib/x11.c b/lib/x11.c index d941d72..7dc504c 100644 --- a/lib/x11.c +++ b/lib/x11.c @@ -211,7 +211,7 @@ void x11_finish(void) { char* text = Selections[CLIPBOARD].text; size_t len = strlen(text); exec_job((char*[]){ "xcpd", NULL }, text, len, NULL); - while (event_poll(100)); + while (exec_poll(-1, 100)); } } diff --git a/tide.c b/tide.c index 7b04b99..7af97c1 100644 --- a/tide.c +++ b/tide.c @@ -211,18 +211,12 @@ void onmouseright(WinRegion id, bool pressed, size_t row, size_t col) { if (win_btnpressed(MouseLeft)) { paste(); } else { - char* text = view_fetch(win_view(id), row, col, risfile); - FetchCmd[1] = text; - if (exec_cmd(FetchCmd) != 0) { - SearchDir *= (x11_keymodsset(ModShift) ? -1 : +1); - free(SearchTerm); - SearchTerm = view_fetch(win_view(id), row, col, risfile); - if (view_findstr(win_view(EDIT), SearchDir, SearchTerm)) { - win_setregion(EDIT); - win_warpptr(EDIT); - } - } else { - free(text); + SearchDir *= (x11_keymodsset(ModShift) ? -1 : +1); + free(SearchTerm); + SearchTerm = view_fetch(win_view(id), row, col, risfile); + if (view_findstr(win_view(EDIT), SearchDir, SearchTerm)) { + win_setregion(EDIT); + win_warpptr(EDIT); } } } @@ -386,7 +380,7 @@ static Tag Builtins[] = { { .tag = "SaveAs", .action.arg = saveas }, { .tag = "Tabs", .action.noarg = tabs }, { .tag = "Undo", .action.noarg = tag_undo }, - { .tag = NULL, .action.noarg = NULL } + { .tag = NULL, .action.noarg = NULL } }; static KeyBinding Bindings[] = { -- 2.54.0