static void test_zmq (flux_reactor_t *reactor) { zctx_t *zctx; void *zs[2]; flux_watcher_t *r, *w; ok ((zctx = zctx_new ()) != NULL, "zmq: created zmq context"); zs[0] = zsocket_new (zctx, ZMQ_PAIR); zs[1] = zsocket_new (zctx, ZMQ_PAIR); ok (zs[0] && zs[1] && zsocket_bind (zs[0], "inproc://test_zmq") == 0 && zsocket_connect (zs[1], "inproc://test_zmq") == 0, "zmq: connected ZMQ_PAIR sockets over inproc"); r = flux_zmq_watcher_create (reactor, zs[0], FLUX_POLLIN, zmqreader, NULL); w = flux_zmq_watcher_create (reactor, zs[1], FLUX_POLLOUT, zmqwriter, NULL); ok (r != NULL && w != NULL, "zmq: nonblocking reader and writer created"); flux_watcher_start (r); flux_watcher_start (w); ok (flux_reactor_run (reactor, 0) == 0, "zmq: reactor ran to completion after %d messages", zmqwriter_msgcount); flux_watcher_stop (r); flux_watcher_stop (w); flux_watcher_destroy (r); flux_watcher_destroy (w); zsocket_destroy (zctx, zs[0]); zsocket_destroy (zctx, zs[1]); zctx_destroy (&zctx); }
void *watchthread (void *arg) { thd_t *t = arg; watch_count_t wc; flux_kvs_txn_t *txn; flux_future_t *f; flux_reactor_t *r; flux_watcher_t *pw = NULL; flux_watcher_t *tw = NULL; if (!(t->h = flux_open (NULL, 0))) log_err_exit ("flux_open"); /* Make sure key doesn't already exist, initial value may affect * test by chance (i.e. initial value = 0, commit 0 and thus no * change) */ if (!(txn = flux_kvs_txn_create ())) log_err_exit ("flux_kvs_txn_create"); if (flux_kvs_txn_unlink (txn, 0, key) < 0) log_err_exit ("flux_kvs_txn_unlink"); if (!(f = flux_kvs_commit (t->h, 0, txn)) || flux_future_get (f, NULL) < 0) log_err_exit ("flux_kvs_commit"); flux_future_destroy (f); flux_kvs_txn_destroy (txn); r = flux_get_reactor (t->h); if (flux_kvs_watch (t->h, key, watch_count_cb, t) < 0) log_err_exit ("flux_kvs_watch %s", key); pw = flux_prepare_watcher_create (r, watch_prepare_cb, NULL); wc.t = t; wc.lastcount = -1; /* So test won't hang if there's a bug */ tw = flux_timer_watcher_create (r, WATCH_TIMEOUT, WATCH_TIMEOUT, watch_timeout_cb, &wc); flux_watcher_start (pw); flux_watcher_start (tw); if (flux_reactor_run (r, 0) < 0) log_err_exit ("flux_reactor_run"); flux_watcher_destroy (pw); flux_watcher_destroy (tw); flux_close (t->h); return NULL; }
static void freectx (void *arg) { ctx_t *ctx = arg; flux_msg_handler_t *w; while ((w = zlist_pop (ctx->handlers))) flux_msg_handler_destroy (w); zlist_destroy (&ctx->handlers); flux_watcher_destroy (ctx->w_prepare); flux_watcher_destroy (ctx->w_check); free (ctx); }
void alloc_ctx_destroy (struct alloc_ctx *ctx) { if (ctx) { int saved_errno = errno;; flux_msg_handler_delvec (ctx->handlers); flux_watcher_destroy (ctx->prep); flux_watcher_destroy (ctx->check); flux_watcher_destroy (ctx->idle); queue_destroy (ctx->inqueue); free (ctx); errno = saved_errno; } }
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; }
/* Timer pops every 1 ms, writing a new value to key. * After 10 calls, it calls kvs_unwatch(). * After 20 calls, it calls flux_reactor_stop(). * The kvs_unwatch_cb() counts the number of times it is called, should be 10. */ void test_unwatch (int argc, char **argv) { struct timer_ctx ctx; flux_reactor_t *r; int count = 0; flux_watcher_t *timer; if (argc != 1) { fprintf (stderr, "Usage: unwatch key\n"); exit (1); } ctx.key = argv[0]; if (!(ctx.h = flux_open (NULL, 0))) log_err_exit ("flux_open"); r = flux_get_reactor (ctx.h); if (kvs_watch_int (ctx.h, ctx.key, unwatch_watch_cb, &count) < 0) log_err_exit ("kvs_watch_int %s", ctx.key); if (!(timer = flux_timer_watcher_create (r, 0.001, 0.001, unwatch_timer_cb, &ctx))) log_err_exit ("flux_timer_watcher_create"); flux_watcher_start (timer); if (flux_reactor_run (r, 0) < 0) log_err_exit ("flux_reactor_run"); if (count != 10) log_msg_exit ("watch called %d times (should be 10)", count); flux_watcher_destroy (timer); flux_close (ctx.h); }
static void subprocess_free (struct subprocess *p) { assert (p != NULL); if (p->sm) zlist_remove (p->sm->processes, (void *) p); zhash_destroy (&p->zhash); hooks_table_free (p); fda_closeall (p->child_fda); if (p->argz) free (p->argz); if (p->envz) free (p->envz); if (p->cwd) free (p->cwd); zio_destroy (p->zio_in); zio_destroy (p->zio_out); zio_destroy (p->zio_err); if (p->parentfd != -1) close (p->parentfd); if (p->childfd != -1) close (p->childfd); flux_watcher_destroy (p->child_watcher); memset (p, 0, sizeof (*p)); free (p); }
void heartbeat_destroy (heartbeat_t *hb) { if (hb) { flux_watcher_destroy (hb->timer); flux_msg_handler_destroy (hb->mh); free (hb); } }
void shutdown_disarm (shutdown_t *s) { if (s->timer) { flux_watcher_stop (s->timer); flux_watcher_destroy (s->timer); s->timer = NULL; } }
static void dispatch_usecount_decr (struct dispatch *d) { if (d && --d->usecount == 0) { flux_watcher_destroy (d->w); zlist_destroy (&d->handlers); zlist_destroy (&d->waiters); free (d); } }
static void test_timer (flux_reactor_t *reactor) { flux_watcher_t *w; errno = 0; ok (!flux_timer_watcher_create (reactor, -1, 0, oneshot, NULL) && errno == EINVAL, "timer: creating negative timeout fails with EINVAL"); ok (!flux_timer_watcher_create (reactor, 0, -1, oneshot, NULL) && errno == EINVAL, "timer: creating negative repeat fails with EINVAL"); ok ((w = flux_timer_watcher_create (reactor, 0, 0, oneshot, NULL)) != NULL, "timer: creating zero timeout works"); flux_watcher_start (w); ok (flux_reactor_run (reactor, 0) == 0, "timer: reactor ran to completion (single oneshot)"); ok (oneshot_ran == true, "timer: oneshot was executed"); oneshot_ran = false; ok (flux_reactor_run (reactor, 0) == 0, "timer: reactor ran to completion (expired oneshot)"); ok (oneshot_ran == false, "timer: expired oneshot was not re-executed"); errno = 0; oneshot_errno = ESRCH; flux_watcher_start (w); ok (flux_reactor_run (reactor, 0) < 0 && errno == ESRCH, "general: reactor stop_error worked with errno passthru"); flux_watcher_stop (w); flux_watcher_destroy (w); ok ((w = flux_timer_watcher_create (reactor, 0.01, 0.01, repeat, NULL)) != NULL, "timer: creating 1ms timeout with 1ms repeat works"); flux_watcher_start (w); ok (flux_reactor_run (reactor, 0) == 0, "timer: reactor ran to completion (single repeat)"); ok (repeat_countdown == 0, "timer: repeat timer stopped itself after countdown"); flux_watcher_stop (w); flux_watcher_destroy (w); }
void hello_destroy (hello_t *hello) { if (hello) { if (hello->nodeset) nodeset_destroy (hello->nodeset); if (hello->timer) flux_watcher_destroy (hello->timer); free (hello); } }
static void freectx (void *arg) { ctx_t *ctx = arg; if (ctx) { zhash_destroy (&ctx->barriers); if (ctx->timer) flux_watcher_destroy (ctx->timer); free (ctx); } }
static void ev_timer_cb (flux_reactor_t *r, flux_watcher_t *w, int revents, void *arg) { cron_entry_t *e = arg; struct cron_event *ev = cron_entry_type_data (e); cron_entry_schedule_task (e); flux_watcher_stop (w); flux_watcher_destroy (w); ev->paused = 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 void reactor_destroy_early (void) { flux_reactor_t *r; flux_watcher_t *w; if (!(r = flux_reactor_create ())) exit (1); if (!(w = flux_idle_watcher_create (r, NULL, NULL))) exit (1); flux_watcher_start (w); flux_reactor_destroy (r); flux_watcher_destroy (w); }
void runlevel_destroy (runlevel_t *r) { if (r) { int i; for (i = 0; i < 4; i++) { if (r->rc[i].p) flux_subprocess_destroy (r->rc[i].p); if (r->rc[i].cmd) flux_cmd_destroy (r->rc[i].cmd); flux_watcher_destroy (r->rc[i].timer); } free (r); } }
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 module_destroy (module_t *p) { assert (p->magic == MODULE_MAGIC); int errnum; if (p->t) { errnum = pthread_join (p->t, NULL); if (errnum) errn_exit (errnum, "pthread_join"); } assert (p->h == NULL); flux_watcher_stop (p->broker_w); flux_watcher_destroy (p->broker_w); zsocket_destroy (p->zctx, p->sock); dlclose (p->dso); zuuid_destroy (&p->uuid); free (p->digest); if (p->argz) free (p->argz); if (p->name) free (p->name); if (p->rmmod_cb) p->rmmod_cb (p, p->rmmod_arg); if (p->rmmod) { flux_msg_t *msg; while ((msg = zlist_pop (p->rmmod))) flux_msg_destroy (msg); } if (p->subs) { char *s; while ((s = zlist_pop (p->subs))) free (s); zlist_destroy (&p->subs); } zlist_destroy (&p->rmmod); p->magic = ~MODULE_MAGIC; free (p); }
static void dispatch_usecount_decr (struct dispatch *d) { flux_msg_handler_t *w; if (d && --d->usecount == 0) { if (d->handlers) { while ((w = zlist_pop (d->handlers))) { assert (w->destroyed); free_msg_handler (w); } zlist_destroy (&d->handlers); } if (d->handlers_new) { while ((w = zlist_pop (d->handlers_new))) { assert (w->destroyed); free_msg_handler (w); } zlist_destroy (&d->handlers_new); } flux_watcher_destroy (d->w); fastpath_free (&d->norm); fastpath_free (&d->group); free (d); } }
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 (); }
int main (int argc, char *argv[]) { int ch; int pad_bytes = 0; char *target; flux_watcher_t *tw = NULL; struct ping_ctx ctx = { .period = 1.0, .rank = NULL, .nodeid = FLUX_NODEID_ANY, .topic = NULL, .pad = NULL, .count = -1, .send_count = 0, .batch = false, }; log_init ("flux-ping"); while ((ch = getopt_long (argc, argv, OPTIONS, longopts, NULL)) != -1) { switch (ch) { case 'h': /* --help */ usage (); break; case 'p': /* --pad bytes */ pad_bytes = strtoul (optarg, NULL, 10); break; case 'd': /* --delay seconds */ ctx.period = strtod (optarg, NULL); if (ctx.period < 0) usage (); break; case 'r': /* --rank NODESET */ ctx.rank = optarg; break; case 'c': /* --count N */ ctx.count = strtoul (optarg, NULL, 10); break; case 'b': /* --batch-request */ ctx.batch = true; break; default: usage (); break; } } if (optind != argc - 1) usage (); if (ctx.batch && ctx.count == -1) log_msg_exit ("--batch should only be used with --count"); target = argv[optind++]; /* Create null terminated pad string for reuse in each message. * By default it's the empty string. */ ctx.pad = xzmalloc (pad_bytes + 1); memset (ctx.pad, 'p', pad_bytes); /* If "rank!" is prepended to the target, and there is no --rank * argument, snip it off and set the rank. If it's just the bare * rank, assume the target is "cmb". */ if (ctx.rank == NULL) { char *p; nodeset_t *ns = NULL; if ((p = strchr (target, '!'))) { *p++ = '\0'; ctx.rank = target; target = p; } else if ((ns = nodeset_create_string (target)) != NULL) { ctx.rank = target; target = "cmb"; nodeset_destroy (ns); } else if (!strcmp (target, "all")) { ctx.rank = target; target = "cmb"; } } /* Use singleton rpc if there's only one nodeid */ if (ctx.rank != NULL) { nodeset_t *ns = nodeset_create_string (ctx.rank); if (ns) { if (nodeset_count (ns) == 1) { ctx.nodeid = nodeset_min (ns); ctx.rank = NULL; } nodeset_destroy (ns); } } ctx.topic = xasprintf ("%s.ping", target); if (!(ctx.h = flux_open (NULL, 0))) log_err_exit ("flux_open"); if (!(ctx.reactor = flux_get_reactor (ctx.h))) log_err_exit ("flux_get_reactor"); /* In batch mode, requests are sent before reactor is started * to process responses. o/w requests are set in a timer watcher. */ if (ctx.batch) { while (ctx.send_count < ctx.count) { send_ping (&ctx); usleep ((useconds_t)(ctx.period * 1E6)); } } else { tw = flux_timer_watcher_create (ctx.reactor, ctx.period, ctx.period, timer_cb, &ctx); if (!tw) log_err_exit ("error creating watchers"); flux_watcher_start (tw); } if (flux_reactor_run (ctx.reactor, 0) < 0) log_err_exit ("flux_reactor_run"); /* Clean up. */ flux_watcher_destroy (tw); free (ctx.topic); free (ctx.pad); flux_close (ctx.h); log_fini (); return 0; }
int main (int argc, char *argv[]) { flux_t *h; flux_reactor_t *r; int last = -1; int ch; flux_future_t *f; log_init ("commit_order"); while ((ch = getopt_long (argc, argv, OPTIONS, longopts, NULL)) != -1) { switch (ch) { case 'h': /* --help */ usage (); break; case 'v': /* --verbose */ verbose = true; break; case 'c': /* --count N */ totcount = strtoul (optarg, NULL, 10); break; case 'f': /* --fanout N */ max_queue_depth = strtoul (optarg, NULL, 10); break; case 'n': /* --namespace=NAME */ if (!(ns = strdup (optarg))) log_err_exit ("out of memory"); break; default: usage (); break; } } if (optind != argc - 1) usage (); key = argv[optind++]; if (totcount < 1 || max_queue_depth < 1) usage (); if (!(h = flux_open (NULL, 0))) log_err_exit ("flux_open"); if (!(r = flux_get_reactor (h))) log_err_exit ("flux_get_reactor"); /* One synchronous put before watch request, so that * watch request doesn't fail with ENOENT. */ f = commit_int (h, key, txcount++); commit_continuation (f, NULL); // destroys f, increments rxcount /* Configure watcher * Wait for one response before unleashing async puts, to ensure * that first value is captured. */ if (!(f = flux_kvs_lookup (h, ns, FLUX_KVS_WATCH, key))) log_err_exit ("flux_kvs_lookup"); watch_continuation (f, &last); // resets f, increments wrxcount if (flux_future_then (f, -1., watch_continuation, &last) < 0) log_err_exit ("flux_future_then"); /* Configure mechanism to keep max_queue_depth (--fanout) put RPCs * outstanding until totcount (--count) reached. */ if (!(w_prep = flux_prepare_watcher_create (r, prep, NULL))) log_err_exit ("flux_prepare_watcher_create"); if (!(w_check = flux_check_watcher_create (r, check, h))) log_err_exit ("flux_check_watcher_create"); if (!(w_idle = flux_idle_watcher_create (r, NULL, NULL))) log_err_exit ("flux_idle_watcher_create"); flux_watcher_start (w_prep); flux_watcher_start (w_check); /* Run until work is exhausted. */ if (flux_reactor_run (r, 0) < 0) log_err_exit ("flux_reactor_run"); flux_watcher_destroy (w_prep); flux_watcher_destroy (w_check); flux_watcher_destroy (w_idle); free (ns); flux_close (h); log_fini (); return 0; }