commit bc10f6a5fcbae63627490a4c11e13a34b1c2525a from: Omar Polo date: Mon Jul 12 19:59:37 2021 UTC refactor: all imsgs are completely asynchronous commit - 4913b479eed668b06a90b1c150b71065a6e2ce36 commit + bc10f6a5fcbae63627490a4c11e13a34b1c2525a blob - cf5c375e1ddc25eb54258080abae9d56e86fede8 blob + d535286a058e3ccba133933c570bdaaea01fe5aa --- ChangeLog +++ ChangeLog @@ -1,5 +1,7 @@ 2021-07-12 Omar Polo + * util.c (dispatch_imsg): refactor: all imsgs are completely asynchronous + * minibuffer.c (minibuffer_taint_hist): bugfix: allow editing minibuffer history 2021-07-10 Omar Polo blob - 963419e60ea0dd6f1e0c50729256dc3ed9d47f2e blob + 881651984cd91e5d9f826a8a9a68219e43f3a436 --- fs.c +++ fs.c @@ -45,10 +45,9 @@ static void handle_session_start(struct imsg*, size_ static void handle_session_tab(struct imsg*, size_t); static void handle_session_end(struct imsg*, size_t); static void handle_dispatch_imsg(int, short, void*); +static int fs_send_ui(int, uint32_t, int, const void *, uint16_t); -static struct event imsgev; -static struct imsgbuf *ibuf; - +static struct imsgev *iev_ui; static FILE *session; static char bookmark_file[PATH_MAX]; @@ -85,22 +84,19 @@ serve_bookmarks(uint32_t peerid) t = "# Bookmarks\n\n" "No bookmarks yet!\n" "Create ~/.telescope/bookmarks.gmi or use `bookmark-page'.\n"; - imsg_compose(ibuf, IMSG_BUF, peerid, 0, -1, t, strlen(t)); - imsg_compose(ibuf, IMSG_EOF, peerid, 0, -1, NULL, 0); - imsg_flush(ibuf); + fs_send_ui(IMSG_BUF, peerid, -1, t, strlen(t)); + fs_send_ui(IMSG_EOF, peerid, -1, NULL, 0); return; } for (;;) { r = fread(buf, 1, sizeof(buf), f); - imsg_compose(ibuf, IMSG_BUF, peerid, 0, -1, buf, r); - imsg_flush(ibuf); + fs_send_ui(IMSG_BUF, peerid, -1, buf, r); if (r != sizeof(buf)) break; } - imsg_compose(ibuf, IMSG_EOF, peerid, 0, -1, NULL, 0); - imsg_flush(ibuf); + fs_send_ui(IMSG_EOF, peerid, -1, NULL, 0); fclose(f); } @@ -108,10 +104,8 @@ serve_bookmarks(uint32_t peerid) static void send_page(struct imsg *imsg, const char *page) { - imsg_compose(ibuf, IMSG_BUF, imsg->hdr.peerid, 0, -1, - page, strlen(page)); - imsg_compose(ibuf, IMSG_EOF, imsg->hdr.peerid, 0, -1, NULL, 0); - imsg_flush(ibuf); + fs_send_ui(IMSG_BUF, imsg->hdr.peerid, -1, page, strlen(page)); + fs_send_ui(IMSG_EOF, imsg->hdr.peerid, -1, NULL, 0); } static void @@ -137,9 +131,8 @@ handle_get(struct imsg *imsg, size_t datalen) send_page(imsg, about_new); } else { p = "# not found!\n"; - imsg_compose(ibuf, IMSG_BUF, imsg->hdr.peerid, 0, -1, p, strlen(p)); - imsg_compose(ibuf, IMSG_EOF, imsg->hdr.peerid, 0, -1, NULL, 0); - imsg_flush(ibuf); + fs_send_ui(IMSG_BUF, imsg->hdr.peerid, -1, p, strlen(p)); + fs_send_ui(IMSG_EOF, imsg->hdr.peerid, -1, NULL, 0); } } @@ -169,8 +162,7 @@ handle_bookmark_page(struct imsg *imsg, size_t datalen res = 0; end: - imsg_compose(ibuf, IMSG_BOOKMARK_OK, 0, 0, -1, &res, sizeof(res)); - imsg_flush(ibuf); + fs_send_ui(IMSG_BOOKMARK_OK, 0, -1, &res, sizeof(res)); } static void @@ -195,9 +187,8 @@ handle_save_cert(struct imsg *imsg, size_t datalen) res = 0; end: - imsg_compose(ibuf, IMSG_SAVE_CERT_OK, imsg->hdr.peerid, 0, -1, + fs_send_ui(IMSG_SAVE_CERT_OK, imsg->hdr.peerid, -1, &res, sizeof(res)); - imsg_flush(ibuf); } static void @@ -257,9 +248,8 @@ handle_update_cert(struct imsg *imsg, size_t datalen) res = rename(sfn, known_hosts_file) != -1; end: - imsg_compose(ibuf, IMSG_UPDATE_CERT_OK, imsg->hdr.peerid, 0, -1, + fs_send_ui(IMSG_UPDATE_CERT_OK, imsg->hdr.peerid, -1, &res, sizeof(res)); - imsg_flush(ibuf); } static void @@ -274,13 +264,11 @@ handle_file_open(struct imsg *imsg, size_t datalen) if ((fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0644)) == -1) { e = strerror(errno); - imsg_compose(ibuf, IMSG_FILE_OPENED, imsg->hdr.peerid, 0, -1, + fs_send_ui(IMSG_FILE_OPENED, imsg->hdr.peerid, -1, e, strlen(e)+1); } else - imsg_compose(ibuf, IMSG_FILE_OPENED, imsg->hdr.peerid, 0, fd, + fs_send_ui(IMSG_FILE_OPENED, imsg->hdr.peerid, fd, NULL, 0); - - imsg_flush(ibuf); } static void @@ -320,10 +308,18 @@ handle_session_end(struct imsg *imsg, size_t datalen) static void handle_dispatch_imsg(int fd, short ev, void *d) { - struct imsgbuf *ibuf = d; - dispatch_imsg(ibuf, handlers, sizeof(handlers)); + struct imsgev *iev = d; + dispatch_imsg(iev, ev, handlers, sizeof(handlers)); } +static int +fs_send_ui(int type, uint32_t peerid, int fd, const void *data, + uint16_t datalen) +{ + return imsg_compose_event(iev_ui, type, peerid, 0, fd, + data, datalen); +} + int fs_init(void) { @@ -358,11 +354,15 @@ fs_main(void) event_init(); - if ((ibuf = calloc(1, sizeof(*ibuf))) == NULL) + /* Setup pipe and event handler to the main process */ + if ((iev_ui = malloc(sizeof(*iev_ui))) == NULL) die(); - imsg_init(ibuf, 3); - event_set(&imsgev, ibuf->fd, EV_READ | EV_PERSIST, handle_dispatch_imsg, ibuf); - event_add(&imsgev, NULL); + imsg_init(&iev_ui->ibuf, 3); + iev_ui->handler = handle_dispatch_imsg; + iev_ui->events = EV_READ; + event_set(&iev_ui->ev, iev_ui->ibuf.fd, iev_ui->events, + iev_ui->handler, iev_ui); + event_add(&iev_ui->ev, NULL); sandbox_fs_process(); blob - 65cfc482332d0226e5db475c9eeca9d9d607f5dd blob + 80b58738cec69d9ab8eb9bca16c88a19139b2c70 --- gemini.c +++ gemini.c @@ -36,9 +36,8 @@ # include #endif -static struct event imsgev; +static struct imsgev *iev_ui; static struct tls_config *tlsconf; -static struct imsgbuf *ibuf; struct req; @@ -72,6 +71,8 @@ static void handle_stop(struct imsg*, size_t); static void handle_quit(struct imsg*, size_t); static void handle_dispatch_imsg(int, short, void*); +static int net_send_ui(int, uint32_t, const void *, uint16_t); + /* TODO: making this customizable */ struct timeval timeout_for_handshake = { 5, 0 }; @@ -292,8 +293,7 @@ close_conn(int fd, short ev, void *d) static void close_with_err(struct req *req, const char *err) { - imsg_compose(ibuf, IMSG_ERR, req->id, 0, -1, err, strlen(err)+1); - imsg_flush(ibuf); + net_send_ui(IMSG_ERR, req->id, err, strlen(err)+1); close_conn(0, 0, req); } @@ -355,8 +355,7 @@ do_handshake(int fd, short ev, void *d) close_with_errf(req, "handshake failed: %s", tls_error(req->ctx)); return; } - imsg_compose(ibuf, IMSG_CHECK_CERT, req->id, 0, -1, hash, strlen(hash)+1); - imsg_flush(ibuf); + net_send_ui(IMSG_CHECK_CERT, req->id, hash, strlen(hash)+1); } static void @@ -445,9 +444,8 @@ parse_reply(struct req *req) *e = '\0'; e++; len = e - req->buf; - imsg_compose(ibuf, IMSG_GOT_CODE, req->id, 0, -1, &code, sizeof(code)); - imsg_compose(ibuf, IMSG_GOT_META, req->id, 0, -1, req->buf, len); - imsg_flush(ibuf); + net_send_ui(IMSG_GOT_CODE, req->id, &code, sizeof(code)); + net_send_ui(IMSG_GOT_META, req->id, req->buf, len); if (20 <= code && code < 30) advance_buf(req, len+1); /* skip \n too */ @@ -468,9 +466,8 @@ copy_body(int fd, short ev, void *d) for (;;) { if (req->off != 0) { - imsg_compose(ibuf, IMSG_BUF, req->id, 0, -1, + net_send_ui(IMSG_BUF, req->id, req->buf, req->off); - imsg_flush(ibuf); req->off = 0; } @@ -482,8 +479,7 @@ copy_body(int fd, short ev, void *d) yield_w(req, copy_body, NULL); return; case 0: - imsg_compose(ibuf, IMSG_EOF, req->id, 0, -1, NULL, 0); - imsg_flush(ibuf); + net_send_ui(IMSG_EOF, req->id, NULL, 0); close_conn(0, 0, req); return; default: @@ -564,10 +560,18 @@ handle_quit(struct imsg *imsg, size_t datalen) static void handle_dispatch_imsg(int fd, short ev, void *d) { - struct imsgbuf *ibuf = d; - dispatch_imsg(ibuf, handlers, sizeof(handlers)); + struct imsgev *iev = d; + dispatch_imsg(iev, ev, handlers, sizeof(handlers)); } +static int +net_send_ui(int type, uint32_t peerid, const void *data, + uint16_t datalen) +{ + return imsg_compose_event(iev_ui, type, peerid, 0, -1, + data, datalen); +} + int client_main(void) { @@ -583,11 +587,14 @@ client_main(void) event_init(); /* Setup pipe and event handler to the main process */ - if ((ibuf = calloc(1, sizeof(*ibuf))) == NULL) + if ((iev_ui = malloc(sizeof(*iev_ui))) == NULL) die(); - imsg_init(ibuf, 3); - event_set(&imsgev, ibuf->fd, EV_READ | EV_PERSIST, handle_dispatch_imsg, ibuf); - event_add(&imsgev, NULL); + imsg_init(&iev_ui->ibuf, 3); + iev_ui->handler = handle_dispatch_imsg; + iev_ui->events = EV_READ; + event_set(&iev_ui->ev, iev_ui->ibuf.fd, iev_ui->events, + iev_ui->handler, iev_ui); + event_add(&iev_ui->ev, NULL); sandbox_net_process(); blob - 3a5e9032c73ddc1d011e95b68f1361f62e2d7bbc blob + 537ed46ae73149851e1f2ca7ec85fc37b1cc6dde --- telescope.c +++ telescope.c @@ -12,7 +12,8 @@ #include "telescope.h" #include "ui.h" -struct event netev, fsev; +static struct imsgev *iev_fs, *iev_net; + struct tabshead tabshead = TAILQ_HEAD_INITIALIZER(tabshead); struct proxylist proxies = TAILQ_HEAD_INITIALIZER(proxies); @@ -29,8 +30,6 @@ static struct proto protos[] = { { NULL, NULL }, }; -static struct imsgbuf *netibuf, *fsibuf; - static void die(void) __attribute__((__noreturn__)); static struct tab *tab_by_id(uint32_t); static void handle_imsg_err(struct imsg*, size_t); @@ -51,6 +50,8 @@ static void handle_dispatch_imsg(int, short, void*); static void load_page_from_str(struct tab*, const char*); static void do_load_url(struct tab*, const char*); static pid_t start_child(enum telescope_process, const char *, int); +static int ui_send_net(int, uint32_t, const void *, uint16_t); +static int ui_send_fs(int, uint32_t, const void *, uint16_t); static imsg_handlerfn *handlers[] = { [IMSG_ERR] = handle_imsg_err, @@ -143,9 +144,7 @@ handle_imsg_check_cert(struct imsg *imsg, size_t datal } strlcpy(e->hash, hash, sizeof(e->hash)); tofu_add(&certs, e); - imsg_compose(fsibuf, IMSG_SAVE_CERT, tab->id, 0, -1, - e, sizeof(*e)); - imsg_flush(fsibuf); + ui_send_fs(IMSG_SAVE_CERT, tab->id, e, sizeof(*e)); } else tofu_res = !strcmp(hash, e->hash); @@ -157,9 +156,8 @@ handle_imsg_check_cert(struct imsg *imsg, size_t datal else tab->trust = TS_TRUSTED; - imsg_compose(netibuf, IMSG_CERT_STATUS, imsg->hdr.peerid, 0, -1, + ui_send_net(IMSG_CERT_STATUS, imsg->hdr.peerid, &tofu_res, sizeof(tofu_res)); - imsg_flush(netibuf); } else { tab->trust = TS_UNTRUSTED; load_page_from_str(tab, "# Certificate mismatch\n"); @@ -173,9 +171,8 @@ handle_imsg_check_cert(struct imsg *imsg, size_t datal static void handle_check_cert_user_choice(int accept, struct tab *tab) { - imsg_compose(netibuf, IMSG_CERT_STATUS, tab->id, 0, -1, - &accept, sizeof(accept)); - imsg_flush(netibuf); + ui_send_net(IMSG_CERT_STATUS, tab->id, &accept, + sizeof(accept)); if (accept) { /* @@ -222,8 +219,7 @@ handle_maybe_save_new_cert(int accept, struct tab *tab strlcat(e->domain, port, sizeof(e->domain)); } strlcpy(e->hash, tab->cert, sizeof(e->hash)); - imsg_compose(fsibuf, IMSG_UPDATE_CERT, 0, 0, -1, e, sizeof(*e)); - imsg_flush(fsibuf); + ui_send_fs(IMSG_UPDATE_CERT, 0, e, sizeof(*e)); tofu_update(&certs, e); @@ -298,8 +294,7 @@ handle_imsg_got_meta(struct imsg *imsg, size_t datalen ui_require_input(tab, tab->code == 11); } else if (tab->code == 20) { if (setup_parser_for(tab)) { - imsg_compose(netibuf, IMSG_PROCEED, tab->id, 0, -1, NULL, 0); - imsg_flush(netibuf); + ui_send_net(IMSG_PROCEED, tab->id, NULL, 0); } else { load_page_from_str(tab, err_pages[UNKNOWN_TYPE_OR_CSET]); ui_yornp("Can't display page, wanna save?", @@ -341,8 +336,7 @@ handle_save_page_path(const char *path, unsigned int t tab = tab_by_id(tabid); tab->path = strdup(path); - imsg_compose(fsibuf, IMSG_FILE_OPEN, tabid, 0, -1, path, strlen(path)+1); - imsg_flush(fsibuf); + ui_send_fs(IMSG_FILE_OPEN, tabid, path, strlen(path)+1); } static void @@ -369,8 +363,7 @@ handle_imsg_file_opened(struct imsg *imsg, size_t data free(page); } else { tab->fd = imsg->fd; - imsg_compose(netibuf, IMSG_PROCEED, tab->id, 0, -1, NULL, 0); - imsg_flush(netibuf); + ui_send_net(IMSG_PROCEED, tab->id, NULL, 0); } } @@ -479,8 +472,8 @@ handle_imsg_update_cert_ok(struct imsg *imsg, size_t d static void handle_dispatch_imsg(int fd, short ev, void *d) { - struct imsgbuf *ibuf = d; - dispatch_imsg(ibuf, handlers, sizeof(handlers)); + struct imsgev *iev = d; + dispatch_imsg(iev, ev, handlers, sizeof(handlers)); } static void @@ -503,9 +496,8 @@ load_about_url(struct tab *tab, const char *url) gemtext_initparser(&tab->buffer.page); - imsg_compose(fsibuf, IMSG_GET, tab->id, 0, -1, + ui_send_fs(IMSG_GET, tab->id, tab->hist_cur->h, strlen(tab->hist_cur->h)+1); - imsg_flush(fsibuf); } void @@ -525,9 +517,8 @@ load_gemini_url(struct tab *tab, const char *url) req.proto = PROTO_GEMINI; - imsg_compose(netibuf, IMSG_GET_RAW, tab->id, 0, -1, + ui_send_net(IMSG_GET_RAW, tab->id, &req, sizeof(req)); - imsg_flush(netibuf); } void @@ -548,9 +539,8 @@ load_via_proxy(struct tab *tab, const char *url, struc req.proto = p->proto; - imsg_compose(netibuf, IMSG_GET_RAW, tab->id, 0, -1, + ui_send_net(IMSG_GET_RAW, tab->id, &req, sizeof(req)); - imsg_flush(netibuf); } static void @@ -646,8 +636,7 @@ load_next_page(struct tab *tab) void stop_tab(struct tab *tab) { - imsg_compose(netibuf, IMSG_STOP, tab->id, 0, -1, NULL, 0); - imsg_flush(netibuf); + ui_send_net(IMSG_STOP, tab->id, NULL, 0); if (tab->fd != -1) { close(tab->fd); @@ -661,8 +650,8 @@ stop_tab(struct tab *tab) void add_to_bookmarks(const char *str) { - imsg_compose(fsibuf, IMSG_BOOKMARK_PAGE, 0, 0, -1, str, strlen(str)+1); - imsg_flush(fsibuf); + ui_send_fs(IMSG_BOOKMARK_PAGE, 0, + str, strlen(str)+1); } void @@ -670,17 +659,14 @@ save_session(void) { struct tab *tab; - imsg_compose(fsibuf, IMSG_SESSION_START, 0, 0, -1, NULL, 0); - imsg_flush(fsibuf); + ui_send_fs(IMSG_SESSION_START, 0, NULL, 0); TAILQ_FOREACH(tab, &tabshead, tabs) { - imsg_compose(fsibuf, IMSG_SESSION_TAB, 0, 0, -1, + ui_send_fs(IMSG_SESSION_TAB, 0, tab->hist_cur->h, strlen(tab->hist_cur->h)+1); - imsg_flush(fsibuf); } - imsg_compose(fsibuf, IMSG_SESSION_END, 0, 0, -1, NULL, 0); - imsg_flush(fsibuf); + ui_send_fs(IMSG_SESSION_END, 0, NULL, 0); } static void @@ -726,6 +712,21 @@ start_child(enum telescope_process p, const char *argv err(1, "execvp(%s)", argv0); } +static int +ui_send_net(int type, uint32_t peerid, const void *data, + uint16_t datalen) +{ + return imsg_compose_event(iev_net, type, peerid, 0, -1, data, + datalen); +} + +static int +ui_send_fs(int type, uint32_t peerid, const void *data, uint16_t datalen) +{ + return imsg_compose_event(iev_fs, type, peerid, 0, -1, data, + datalen); +} + static void __attribute__((noreturn)) usage(int r) { @@ -737,8 +738,8 @@ usage(int r) int main(int argc, char * const *argv) { - struct imsgbuf net_ibuf, fs_ibuf; - int net_fds[2], fs_fds[2]; + struct imsgev net_ibuf, fs_ibuf; + int pipe2net[2], pipe2fs[2]; int ch, configtest = 0, fail = 0; int has_url = 0; int proc = -1; @@ -818,17 +819,19 @@ main(int argc, char * const *argv) } /* Start children. */ - if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fs_fds) == -1) + if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe2fs) == -1) err(1, "socketpair"); - start_child(PROC_FS, argv0, fs_fds[1]); - imsg_init(&fs_ibuf, fs_fds[0]); - fsibuf = &fs_ibuf; + start_child(PROC_FS, argv0, pipe2fs[1]); + imsg_init(&fs_ibuf.ibuf, pipe2fs[0]); + iev_fs = &fs_ibuf; + iev_fs->handler = handle_dispatch_imsg; - if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, net_fds) == -1) + if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe2net) == -1) err(1, "socketpair"); - start_child(PROC_NET, argv0, net_fds[1]); - imsg_init(&net_ibuf, net_fds[0]); - netibuf = &net_ibuf; + start_child(PROC_NET, argv0, pipe2net[1]); + imsg_init(&net_ibuf.ibuf, pipe2net[0]); + iev_net = &net_ibuf; + iev_net->handler = handle_dispatch_imsg; setproctitle("ui"); @@ -839,13 +842,16 @@ main(int argc, char * const *argv) event_init(); - event_set(&netev, netibuf->fd, EV_READ | EV_PERSIST, - handle_dispatch_imsg, netibuf); - event_add(&netev, NULL); + /* Setup event handlers for pipes to fs/net */ + iev_fs->events = EV_READ; + event_set(&iev_fs->ev, iev_fs->ibuf.fd, iev_fs->events, + iev_fs->handler, iev_fs); + event_add(&iev_fs->ev, NULL); - event_set(&fsev, fsibuf->fd, EV_READ | EV_PERSIST, - handle_dispatch_imsg, fsibuf); - event_add(&fsev, NULL); + iev_net->events = EV_READ; + event_set(&iev_net->ev, iev_net->ibuf.fd, iev_net->events, + iev_net->handler, iev_net); + event_add(&iev_net->ev, NULL); if (ui_init()) { load_last_session(session_new_tab_cb); @@ -857,11 +863,8 @@ main(int argc, char * const *argv) ui_end(); } - imsg_compose(netibuf, IMSG_QUIT, 0, 0, -1, NULL, 0); - imsg_flush(netibuf); + ui_send_fs(IMSG_QUIT, 0, NULL, 0); + ui_send_net(IMSG_QUIT, 0, NULL, 0); - imsg_compose(fsibuf, IMSG_QUIT, 0, 0, -1, NULL, 0); - imsg_flush(fsibuf); - return 0; } blob - 1384bbb676be2cec810813e94257bcbe9b8ff103 blob + 18b35c9587fc01b7b09a7b890ca79d2554a20783 --- telescope.h +++ telescope.h @@ -27,6 +27,13 @@ #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define GEMINI_URL_LEN 1024 + +struct imsgev { + struct imsgbuf ibuf; + void (*handler)(int, short, void *); + struct event ev; + short events; +}; enum imsg_type { /* ui <-> client/fs */ @@ -383,7 +390,8 @@ int mark_nonblock(int); int has_prefix(const char*, const char*); int unicode_isspace(uint32_t); int unicode_isgraph(uint32_t); -void dispatch_imsg(struct imsgbuf*, imsg_handlerfn**, size_t); +void dispatch_imsg(struct imsgev*, short, imsg_handlerfn**, size_t); +int imsg_compose_event(struct imsgev *, uint16_t, uint32_t, pid_t, int, const void *, uint16_t); /* wrap.c */ void erase_buffer(struct buffer *); blob - 5d0267624c08d1c1f99cedfe2af9e7b944e563d8 blob + 9d51f36474be436c2bd10eae4ecd1f741a37ebd8 --- util.c +++ util.c @@ -22,6 +22,8 @@ #include #include +static void imsg_event_add(struct imsgev *); + int mark_nonblock(int fd) { @@ -61,27 +63,47 @@ unicode_isgraph(uint32_t cp) return 1; } +static void +imsg_event_add(struct imsgev *iev) +{ + iev->events = EV_READ; + if (iev->ibuf.w.queued) + iev->events |= EV_WRITE; + + event_del(&iev->ev); + event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); + event_add(&iev->ev, NULL); +} + void -dispatch_imsg(struct imsgbuf *ibuf, imsg_handlerfn **handlers, size_t size) +dispatch_imsg(struct imsgev *iev, short event, imsg_handlerfn **handlers, + size_t size) { - struct imsg imsg; - size_t datalen, i; - ssize_t n; + struct imsgbuf *ibuf; + struct imsg imsg; + size_t datalen, i; + ssize_t n; - if ((n = imsg_read(ibuf)) == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) - return; - _exit(1); + ibuf = &iev->ibuf; + + if (event & EV_READ) { + if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) + err(1, "imsg_read error"); + if (n == 0) + err(1, "connection closed"); } + if (event & EV_WRITE) { + if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) + err(1, "msgbuf_write"); + if (n == 0) + err(1, "connection closed"); + } - if (n == 0) - _exit(1); - for (;;) { if ((n = imsg_get(ibuf, &imsg)) == -1) _exit(1); if (n == 0) - return; + break; datalen = imsg.hdr.len - IMSG_HEADER_SIZE; i = imsg.hdr.type; if (i > (size / sizeof(imsg_handlerfn*)) || handlers[i] == NULL) @@ -89,4 +111,19 @@ dispatch_imsg(struct imsgbuf *ibuf, imsg_handlerfn **h handlers[i](&imsg, datalen); imsg_free(&imsg); } + + imsg_event_add(iev); } + +int +imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, + pid_t pid, int fd, const void *data, uint16_t datalen) +{ + int ret; + + if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, + datalen) != -1)) + imsg_event_add(iev); + + return ret; +}