static int parent_io_setup (struct subprocess *p) { /* * Close child end of stdio in parent: */ if (zio_close_src_fd (p->zio_in) < 0 || zio_close_dst_fd (p->zio_out) < 0 || zio_close_dst_fd (p->zio_err) < 0) return (-1); return (0); }
static int child_io_setup (struct subprocess *p) { /* * Close parent end of stdio in child: */ if (zio_close_dst_fd (p->zio_in) < 0 || zio_close_src_fd (p->zio_out) < 0 || zio_close_src_fd (p->zio_err) < 0) return (-1); /* * Dup this process' fds onto zio */ if ( (dup2_fd (zio_src_fd (p->zio_in), STDIN_FILENO) < 0) || (dup2_fd (zio_dst_fd (p->zio_out), STDOUT_FILENO) < 0) || (dup2_fd (zio_dst_fd (p->zio_err), STDERR_FILENO) < 0)) return (-1); return (0); }
void zio_destroy (zio_t *z) { if (z == NULL) return; assert (z->magic == ZIO_MAGIC); if (zio_is_in_handler (z)) { zio_set_destroyed (z); return; } if (z->buf) cbuf_destroy (z->buf); free (z->name); free (z->prefix); zio_close_src_fd (z); zio_close_dst_fd (z); flux_watcher_destroy (z->reader); flux_watcher_destroy (z->writer); assert ((z->magic = ~ZIO_MAGIC)); free (z); }
static int zio_close (zio_t *zio) { if (zio->flags & ZIO_CLOSED) { /* Already closed */ errno = EINVAL; return (-1); } zio_debug (zio, "zio_close\n"); if (zio_reader (zio)) zio_close_src_fd (zio); else if (zio_writer (zio)) { zio_close_dst_fd (zio); /* For writer zio object, consider close(dstfd) * as "EOF sent" */ zio->flags |= ZIO_EOF_SENT; } zio->flags |= ZIO_CLOSED; if (zio->close) return (*zio->close) (zio, zio->arg); return (0); }
int main (int argc, char **argv) { zio_t *zio; int init_fds; const char *name; struct counts c; int fd; flux_reactor_t *r; flux_watcher_t *w; memset (&c, 0, sizeof (c)); plan (NO_PLAN); test_encode (); ok ((r = flux_reactor_create (0)) != NULL, "flux reactor created"); init_fds = fdcount (); diag ("initial fd count: %d", init_fds); /* simple reader tests */ ok ((zio = zio_pipe_reader_create ("test1", &c)) != NULL, "reader: zio_pipe_reader_create works"); ok ((name = zio_name (zio)) != NULL && !strcmp (name, "test1"), "reader: zio_name returns correct name"); ok (zio_set_close_cb (zio, close_reader) == 0, "reader: zio_set_close_cb works"); ok (zio_set_send_cb (zio, send_reader) == 0, "reader: zio_set_send_cb works"); ok (zio_reactor_attach (zio, r) == 0, "reader: zio_reactor_attach works"); ok ((fd = zio_dst_fd (zio)) >= 0, "reader: zio_dst_fd returned valid file descriptor"); ok (write (fd, "narf!", 5) == 5, "reader: wrote narf! to reader pipe"); ok (zio_close_dst_fd (zio) == 0, "reader: zio_close_dst_fd succeeded"); ok (flux_reactor_run (r, 0) == 0, "reader: reactor completed successfully"); ok (c.send_reader == 1, "reader: send function called once for EOF + incomplete line"); errno = 0; zio_destroy (zio); ok (init_fds == fdcount (), "reader: zio_destroy leaks no file descriptors"); /* simple writer tests */ ok ((zio = zio_pipe_writer_create ("test2", &c)) != NULL, "writer: zio_pipe_writer_create works"); ok ((name = zio_name (zio)) != NULL && !strcmp (name, "test2"), "writer: zio_name returns correct name"); ok (zio_set_close_cb (zio, close_writer) == 0, "writer: zio_set_close_cb works"); ok ((fd = zio_src_fd (zio)) >= 0, "writer: zio_src_fd returned valid file descriptor"); w = flux_fd_watcher_create (r, fd, FLUX_POLLIN, fd_read, &c); ok (w != NULL, "writer: created fd watcher"); flux_watcher_start (w); ok (zio_write (zio, "narf!", 5) == 5, "writer: zio_write narf! works"); ok (zio_write_eof (zio) == 0, "writer: zio_write_eof works"); ok (flux_reactor_run (r, 0) == 0, "writer: reactor completed successfully"); ok (c.fd_read_errors == 0 && c.fd_read_data == 5 && c.fd_read_eof == 1, "writer: read narf + EOF on read end of pipe"); ok (c.close_writer == 1, "writer: close callback invoked"); zio_destroy (zio); ok (init_fds == fdcount (), "writer: zio_destroy leaks no file descriptors"); flux_watcher_destroy (w); flux_reactor_destroy (r); done_testing (); }