static client_t * client_create (ctx_t *ctx, int fd) { client_t *c; socklen_t crlen = sizeof (c->ucred); flux_t h = ctx->h; c = xzmalloc (sizeof (*c)); c->fd = fd; if (!(c->uuid = zuuid_new ())) oom (); c->ctx = ctx; if (!(c->disconnect_notify = zhash_new ())) oom (); if (!(c->subscriptions = zlist_new ())) oom (); if (!(c->outqueue = zlist_new ())) oom (); if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &c->ucred, &crlen) < 0) { flux_log (h, LOG_ERR, "getsockopt SO_PEERCRED: %s", strerror (errno)); goto error; } assert (crlen == sizeof (c->ucred)); /* Deny connections by uid other than session owner for now. */ if (c->ucred.uid != ctx->session_owner) { flux_log (h, LOG_ERR, "connect by uid=%d pid=%d denied", c->ucred.uid, (int)c->ucred.pid); goto error; } c->inw = flux_fd_watcher_create (fd, FLUX_POLLIN, client_read_cb, c); c->outw = flux_fd_watcher_create (fd, FLUX_POLLOUT, client_write_cb, c); if (!c->inw || !c->outw) { flux_log (h, LOG_ERR, "flux_fd_watcher_create: %s", strerror (errno)); goto error; } flux_fd_watcher_start (h, c->inw); flux_msg_iobuf_init (&c->inbuf); flux_msg_iobuf_init (&c->outbuf); if (set_nonblock (c->fd, true) < 0) { flux_log (h, LOG_ERR, "set_nonblock: %s", strerror (errno)); goto error; } return (c); error: client_destroy (c); return NULL; }
void *server_thread (void *arg) { struct context *ctx = arg; flux_reactor_t *reactor = NULL; flux_watcher_t *w = NULL; if (!(reactor = flux_reactor_create (0))) goto done; if (!(w = flux_fd_watcher_create (reactor, ctx->fds[1], FLUX_POLLIN, s_io_cb, ctx))) goto done; flux_watcher_start (w); ctx->exit_rc = -1; if (flux_reactor_run (reactor, 0) < 0) goto done; ctx->exit_rc = 0; done: if (w) flux_watcher_destroy (w); if (reactor) flux_reactor_destroy (reactor); return NULL; }
int mod_main (flux_t h, int argc, char **argv) { ctx_t *ctx = getctx (h); char *sockpath = NULL, *dfltpath = NULL; int rc = -1; /* Parse args. */ if (argc > 0) sockpath = argv[0]; if (!sockpath) sockpath = dfltpath = xasprintf ("%s/flux-api", flux_get_tmpdir ()); /* Create listen socket and watcher to handle new connections */ if ((ctx->listen_fd = listener_init (ctx, sockpath)) < 0) goto done; if (!(ctx->listen_w = flux_fd_watcher_create (ctx->listen_fd, FLUX_POLLIN | FLUX_POLLERR, listener_cb, ctx))) { flux_log (h, LOG_ERR, "flux_fd_watcher_create: %s", strerror (errno)); goto done; } flux_fd_watcher_start (h, ctx->listen_w); /* Create/start event/response message watchers */ if (flux_msg_watcher_addvec (h, htab, ctx) < 0) { flux_log (h, LOG_ERR, "flux_msg_watcher_addvec: %s", strerror (errno)); goto done; } /* Start reactor */ if (flux_reactor_start (h) < 0) { flux_log (h, LOG_ERR, "flux_reactor_start: %s", strerror (errno)); goto done; } rc = 0; done: if (dfltpath) free (dfltpath); flux_msg_watcher_delvec (h, htab); flux_fd_watcher_destroy (ctx->listen_w); if (ctx->listen_fd >= 0) { if (close (ctx->listen_fd) < 0) flux_log (h, LOG_ERR, "close listen_fd: %s", strerror (errno)); } if (ctx->clients) { client_t *c; while ((c = zlist_pop (ctx->clients))) client_destroy (c); } return rc; }
/* * Schedule pending data to write to zio->dstfd */ static int zio_flux_writer_schedule (zio_t *zio) { if (!zio->reactor) return (-1); if (!zio->writer) zio->writer = flux_fd_watcher_create (zio->reactor, zio->dstfd, FLUX_POLLOUT, zio_flux_writer_cb, zio); if (!zio->writer) return (-1); flux_watcher_start (zio->writer); return (0); }
static int zio_flux_reader_poll (zio_t *zio) { if (!zio->reactor) return (-1); if (!zio->reader) zio->reader = flux_fd_watcher_create (zio->reactor, zio->srcfd, FLUX_POLLIN, zio_flux_read_cb, zio); if (!zio->reader) return (-1); flux_watcher_start (zio->reader); return (0); }
static void test_fd (flux_reactor_t *reactor) { int fd[2]; flux_watcher_t *r, *w; ok (socketpair (PF_LOCAL, SOCK_STREAM, 0, fd) == 0 && set_nonblock (fd[0]) == 0 && set_nonblock (fd[1]) == 0, "fd: successfully created non-blocking socketpair"); r = flux_fd_watcher_create (reactor, fd[0], FLUX_POLLIN, fdreader, NULL); w = flux_fd_watcher_create (reactor, fd[1], FLUX_POLLOUT, fdwriter, NULL); ok (r != NULL && w != NULL, "fd: reader and writer created"); flux_watcher_start (r); flux_watcher_start (w); ok (flux_reactor_run (reactor, 0) == 0, "fd: reactor ran to completion after %lu bytes", fdwriter_bufsize); flux_watcher_stop (r); flux_watcher_stop (w); flux_watcher_destroy (r); flux_watcher_destroy (w); close (fd[0]); close (fd[1]); }
static void attach (flux_t *h, const char *key, bool rawtty, int kzoutflags, int blocksize) { t_kzutil_ctx_t *ctx = xzmalloc (sizeof (*ctx)); char *name; int fdin = dup (STDIN_FILENO); struct termios saved_tio; flux_reactor_t *r = flux_get_reactor (h); flux_watcher_t *w = NULL; log_msg ("process attached to %s", key); ctx->h = h; ctx->blocksize = blocksize; /* FIXME: need a ~. style escape sequence to terminate stdin * in raw mode. */ if (rawtty) { if (fd_set_raw (fdin, &saved_tio, true) < 0) log_err_exit ("fd_set_raw stdin"); } if (fd_set_nonblocking (fdin, true) < 0) log_err_exit ("fd_set_nonblocking stdin"); if (asprintf (&name, "%s.stdin", key) < 0) oom (); if (!(ctx->kz[0] = kz_open (h, name, kzoutflags))) if (errno == EEXIST) log_err ("disabling stdin"); else log_err_exit ("%s", name); else { if (!(w = flux_fd_watcher_create (r, fdin, FLUX_POLLIN, attach_stdin_ready_cb, ctx))) log_err_exit ("flux_fd_watcher_create %s", name); flux_watcher_start (w); } free (name); if (asprintf (&name, "%s.stdout", key) < 0) oom (); if (!(ctx->kz[1] = kz_open (h, name, KZ_FLAGS_READ | KZ_FLAGS_NONBLOCK))) log_err_exit ("kz_open %s", name); if (kz_set_ready_cb (ctx->kz[1], attach_stdout_ready_cb, ctx) < 0) log_err_exit ("kz_set_ready_cb %s", name); free (name); ctx->readers++; if (asprintf (&name, "%s.stderr", key) < 0) oom (); if (!(ctx->kz[2] = kz_open (h, name, KZ_FLAGS_READ | KZ_FLAGS_NONBLOCK))) log_err_exit ("kz_open %s", name); if (kz_set_ready_cb (ctx->kz[2], attach_stderr_ready_cb, ctx) < 0) log_err_exit ("kz_set_ready_cb %s", name); free (name); ctx->readers++; /* Reactor terminates when ctx->readers reaches zero, i.e. * when EOF is read from remote stdout and stderr. * (Note: if they are already at eof, we will have already terminated * before the reactor is started, since kvs_watch callbacks make one * call to the callback in the context of the caller). */ if (ctx->readers > 0) { if (flux_reactor_run (r, 0) < 0) log_err_exit ("flux_reactor_run"); } (void)kz_close (ctx->kz[1]); (void)kz_close (ctx->kz[2]); /* FIXME: tty state needs to be restored on all exit paths. */ if (rawtty) { if (fd_set_raw (fdin, &saved_tio, false) < 0) log_err_exit ("fd_set_raw stdin"); } flux_watcher_destroy (w); free (ctx); }
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 (); }