-/** @brief State structure for a buffered reader */
-struct ev_reader {
- struct buffer b;
- int fd;
- ev_reader_callback *callback;
- ev_error_callback *error_callback;
- void *u;
- ev_source *ev;
- int eof;
-};
+/** @brief Shut down a reader
+ *
+ * This is the only path through which we cancel and close the file descriptor.
+ * As with the writer case it is given timeout signature to allow it be
+ * deferred to the next iteration of the event loop.
+ *
+ * We only call @p error_callback if @p error is nonzero (unlike the writer
+ * case).
+ */
+static int reader_shutdown(ev_source *ev,
+ const attribute((unused)) struct timeval *now,
+ void *u) {
+ ev_reader *const r = u;
+
+ if(r->fd == -1)
+ return 0; /* already shut down */
+ D(("reader_shutdown fd=%d", r->fd));
+ ev_fd_cancel(ev, ev_read, r->fd);
+ r->eof = 1;
+ if(r->writer) {
+ D(("found a tied writer"));
+ /* If there is a writer still around we just untie it */
+ r->writer->reader = 0;
+ shutdown(r->fd, SHUT_RD); /* there'll be no more reads */
+ } else {
+ D(("no tied writer found"));
+ /* There's no writer so we are free to close the FD */
+ xclose(r->fd);
+ }
+ r->fd = -1;
+ if(r->error)
+ return r->error_callback(ev, r->error, r->u);
+ else
+ return 0;
+}