From 9a4cfbfab0bc08fb2ec342a310c63685443cab1f Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 8 Feb 2017 02:18:33 +0000 Subject: [PATCH 01/13] libutil/coproc: handle 32-bit pointers on arm7l Construct makecontext() arugments properly on systems like arm7l that have 32 bit pointers. --- configure.ac | 1 + src/common/libutil/coproc.c | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index f8c2e10c2a0f..e70f9d290838 100644 --- a/configure.ac +++ b/configure.ac @@ -76,6 +76,7 @@ AC_TYPE_SIZE_T AX_COMPILE_CHECK_SIZEOF(int) AX_COMPILE_CHECK_SIZEOF(long) AX_COMPILE_CHECK_SIZEOF(long long) +AX_COMPILE_CHECK_SIZEOF(uintptr_t, [#include ]) AX_COMPILE_CHECK_SIZEOF(size_t, [#include ]) diff --git a/src/common/libutil/coproc.c b/src/common/libutil/coproc.c index 4eef972c0d98..7e99e7fce588 100644 --- a/src/common/libutil/coproc.c +++ b/src/common/libutil/coproc.c @@ -79,7 +79,13 @@ void coproc_destroy (coproc_t *c) static void trampoline (const unsigned int high, const unsigned int low) { +#if SIZEOF_UINTPTR_T == SIZEOF_INT + coproc_t *c = (coproc_t *)(uintptr_t)(high); +#elif SIZEOF_UINTPTR_T == 8 && SIZEOF_INT == 4 coproc_t *c = (coproc_t *)((((uintptr_t)high) << 32) | low); +#else +#error FIXME: unexpected pointer/integer size +#endif assert (c->magic == COPROC_MAGIC); c->rc = c->cb (c, c->arg); @@ -156,10 +162,15 @@ int coproc_start (coproc_t *c, void *arg) return -1; } - const unsigned int high = ((uintptr_t)c) >> 32; - const unsigned int low = ((uintptr_t)c) & 0xffffffff; - makecontext (&c->uc, (void (*)(void))trampoline, 2, high, low); - +#if SIZEOF_UINTPTR_T == SIZEOF_INT + makecontext (&c->uc, (void (*)(void))trampoline, 2, + (uintptr_t)c, 0); +#elif SIZEOF_UINTPTR_T == 8 && SIZEOF_INT == 4 + makecontext (&c->uc, (void (*)(void))trampoline, 2, + ((uintptr_t)c) >> 32, ((uintptr_t)c) & 0xffffffff); +#else +#error FIXME: unexpected pointer/integer size +#endif c->arg = arg; c->state = CS_RUNNING; return swapcontext (&c->parent, &c->uc); From 2cbd20ceedcee1866192f01a28ca26762927f670 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 8 Feb 2017 04:48:08 +0000 Subject: [PATCH 02/13] cmd/flux-ping: use portable size_t format specifier Use %zu format specifier to refer to a size_t argument to avoid compilation errors on arm7l. --- src/cmd/flux-ping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/flux-ping.c b/src/cmd/flux-ping.c index 0aaebd3f392f..ea1028795e33 100644 --- a/src/cmd/flux-ping.c +++ b/src/cmd/flux-ping.c @@ -137,7 +137,7 @@ void ping_continuation (flux_rpc_t *rpc, void *arg) if (flux_rpc_next (rpc) < 0) { if (pdata->rpc_count) { if (ctx->rank_count > 1) { - printf ("%s!%s pad=%lu seq=%d time=(%0.3f:%0.3f:%0.3f) ms " + printf ("%s!%s pad=%zu seq=%d time=(%0.3f:%0.3f:%0.3f) ms " "stddev %0.3f\n", ctx->rank, ctx->topic, strlen (ctx->pad), pdata->seq, tstat_min (tstat), tstat_mean (tstat), From 806e84cbc5263690fe46cf7b94c501f6e7e466b8 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 8 Feb 2017 04:49:42 +0000 Subject: [PATCH 03/13] cmd/flux-jstat: use portable int64_t format specifer Use %PRIi64 not %ld to refer to int64_t argument to avoid compilation errors on arm7l. --- src/cmd/flux-jstat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/flux-jstat.c b/src/cmd/flux-jstat.c index baed97b7746a..9424952b9e65 100644 --- a/src/cmd/flux-jstat.c +++ b/src/cmd/flux-jstat.c @@ -203,7 +203,7 @@ static int handle_query_req (flux_t *h, int64_t j, const char *k, const char *n) return -1; } jcb = Jfromstr (jcbstr); - fprintf (ctx->op, "Job Control Block: attribute %s for job %ld\n", k, j); + fprintf (ctx->op, "Job Control Block: attribute %s for job %"PRIi64"\n", k, j); fprintf (ctx->op, "%s\n", jcb == NULL ? jcbstr : json_object_to_json_string_ext (jcb, JSON_C_TO_STRING_PRETTY)); Jput (jcb); From c126c10f9576c86cc47c66cf24147a55e42cd02b Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 8 Feb 2017 06:18:06 +0000 Subject: [PATCH 04/13] test/coproc: avoid excessive VM usage Problem: running 10,000 coprocs causes coproc_create() uses 10000*2mb = 20gb of VM, resulting in ENOMEM on a system with 32-bit pointers. The requested amount of memory cannot be represented in 32-bit pointers. In addition, the default vm.overcommit_memory setting (0: heuristic overcommit handling) may reject an allocation greatly in excess of physical memory. Run 500 instead of 10K coprocesses, which is still a reasonable test. In addition, clean up the test so that it doesn't produce a series of cascading segfaults and obscure failures when this happens. Fail the first test and continue on with however many coprocs were able to be allocated. --- src/common/libutil/test/coproc.c | 63 +++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/src/common/libutil/test/coproc.c b/src/common/libutil/test/coproc.c index f019bef89eee..488af0be3ec4 100644 --- a/src/common/libutil/test/coproc.c +++ b/src/common/libutil/test/coproc.c @@ -143,32 +143,61 @@ int main (int argc, char *argv[]) ok (pthread_join (t, NULL) == 0, "pthread_join OK"); - coproc_t *cps[10000]; - for (i = 0; i < 10000; i++) { - if (!(cps[i] = coproc_create (bar_cb))) +// N.B. coproc_create allocates ~2mb per coproc +#define NUM_COPROCS 500 + coproc_t *cps[NUM_COPROCS]; + for (i = 0; i < NUM_COPROCS; i++) { + if (!(cps[i] = coproc_create (bar_cb))) { + diag ("coproc_create #%d failed: %s", i, strerror (errno)); break; - if (coproc_start (cps[i], NULL) < 0 || coproc_returned (cps[i], NULL)) + } + if (coproc_start (cps[i], NULL) < 0) { + diag ("coproc_start #%d failed", i); break; + } + if (coproc_returned (cps[i], NULL)) { + diag ("coproc_returned #%d returned true", i); + break; + } } - ok (i == 10000, - "started 10000 coprocs that yielded"); - for (i = 0; i < 10000; i++) { - if (coproc_resume (cps[i]) < 0 || coproc_returned (cps[i], NULL)) + ok (i == NUM_COPROCS, + "started %d coprocs that yielded", NUM_COPROCS); + int num = i; + if (num != NUM_COPROCS) + diag ("continuing with %d procs", num); + for (i = 0; i < num; i++) { + if (coproc_resume (cps[i]) < 0) { + diag ("coproc_resume #%d failed", i); + break; + } + if (coproc_returned (cps[i], NULL)) { + diag ("coproc_returned #%d returned true", i); break; + } } - ok (i == 10000, - "resumed 10000 coprocs that yielded"); + ok (i == num, + "resumed %d coprocs that yielded", num); death = true; - for (i = 0; i < 10000; i++) { - if (coproc_resume (cps[i]) < 0 || !coproc_returned (cps[i], &rc) - || rc != 0) + for (i = 0; i < num; i++) { + if (coproc_resume (cps[i]) < 0) { + diag ("coproc_resume #%d failed", i); + break; + } + if (!coproc_returned (cps[i], &rc)) { + diag ("coproc_returned #%d returned false", i); + break; + } + if (rc != 0) { + diag ("rc #%d == %d, wanted 0", i, rc); break; + } } - ok (i == 10000, - "resumed 10000 coprocs that exited with rc=0"); + ok (i == num, + "resumed %d coprocs that exited with rc=0", num); - for (i = 0; i < 10000; i++) - coproc_destroy (cps[i]); + for (i = 0; i < num; i++) + if (cps[i]) + coproc_destroy (cps[i]); /* Test stack guard page(s) */ From de0134fe5bc0cc19815ccd1d137dcd5abb0514d5 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 8 Feb 2017 06:32:28 +0000 Subject: [PATCH 05/13] test/broker: fix signed integer issue in attr test Problem: broker attr test fails on arm7l architecture. Change strtol() to strtoul() when converting UINT_MAX - 1. --- src/broker/test/attr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/broker/test/attr.c b/src/broker/test/attr.c index 74281d1466a5..8f912084f45f 100644 --- a/src/broker/test/attr.c +++ b/src/broker/test/attr.c @@ -174,7 +174,7 @@ int main (int argc, char **argv) "attr_get on active uint32_t tracks value: %s", val); b = UINT_MAX - 1; ok (attr_get (attrs, "b", &val, NULL) == 0 - && strtol (val, NULL, 10) == UINT_MAX - 1, + && strtoul (val, NULL, 10) == UINT_MAX - 1, "attr_get on active uint32_t tracks value: %s", val); ok (attr_set (attrs, "b", "0", false) == 0 && b == 0, From 2122ff985d25cdff7aff7945c94226bc6075750a Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 8 Feb 2017 17:38:11 +0000 Subject: [PATCH 06/13] lua-affinity: handle 32-bit lua_Integer typedef Backport of grondo/lua-affinity#2 to copy of lua-affinity in flux-core. Fixes #975 --- src/bindings/lua/lua-affinity/lua-affinity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings/lua/lua-affinity/lua-affinity.c b/src/bindings/lua/lua-affinity/lua-affinity.c index 319200254b80..534818be16de 100644 --- a/src/bindings/lua/lua-affinity/lua-affinity.c +++ b/src/bindings/lua/lua-affinity/lua-affinity.c @@ -36,7 +36,7 @@ #include "cpuset-str.h" -#define MAX_LUAINT (0xfffffffffffff0) +#define MAX_LUAINT ((1ULL<<(8*(sizeof(lua_Integer)-1)))-0x10) static cpu_set_t * l_cpu_set_alloc (lua_State *L) { From 3b7750cb613418887c34e601d20e318a010e2028 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 8 Feb 2017 19:38:12 +0000 Subject: [PATCH 07/13] cmd/flux-ping: handle 32-bit tv_sec/tv_usec Problem: flux-ping segfaults in flux_rpcf_multi() on arm7l, which has 32-bit struct timeval members. The "I" format specifier refers to a 64-bit argument in json_vpack_ex() and passing 32 bit arguments triggers a segfault. The segfault is avoided in flux-ping by casting tv_sec and tv_usec arguments to uint64_t. --- src/cmd/flux-ping.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/flux-ping.c b/src/cmd/flux-ping.c index ea1028795e33..4be8358b1e1b 100644 --- a/src/cmd/flux-ping.c +++ b/src/cmd/flux-ping.c @@ -176,8 +176,8 @@ void send_ping (struct ping_ctx *ctx) rpc = flux_rpcf_multi (ctx->h, ctx->topic, ctx->rank, 0, "{s:i s:I s:I s:s}", "seq", ctx->send_count, - "time.tv_sec", t0.tv_sec, - "time.tv_nsec", t0.tv_nsec, + "time.tv_sec", (uint64_t)t0.tv_sec, + "time.tv_nsec", (uint64_t)t0.tv_nsec, "pad", ctx->pad); if (!rpc) log_err_exit ("flux_rpcf_multi"); From 98745614b2f2cfd6b12f900f3327813a7abedd0d Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 8 Feb 2017 19:52:22 +0000 Subject: [PATCH 08/13] test/ping: increase timeouts on two tests Problem: 5s timeouts are too tight on tests 1 and 6 on are too small for some systems. Actual runtimes on raspberry pi were 5.7s and 8.4s, respectively. Increase timeouts to 10s and 20s. --- t/t0007-ping.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/t/t0007-ping.t b/t/t0007-ping.t index 893cb295ebfc..b000be4624d5 100755 --- a/t/t0007-ping.t +++ b/t/t0007-ping.t @@ -13,7 +13,7 @@ invalid_rank() { } test_expect_success 'ping: 10K 1K byte echo requests' ' - run_timeout 5 flux ping --pad 1024 --count 10240 --interval 0 0 + run_timeout 10 flux ping --pad 1024 --count 10240 --interval 0 0 ' test_expect_success 'ping: 1K 10K byte echo requests' ' @@ -33,7 +33,7 @@ test_expect_success 'ping: 10 1M byte echo requests (batched)' ' ' test_expect_success 'ping: 1K 10K byte echo requests (batched)' ' - run_timeout 5 flux ping --pad 10240 --count 1024 --batch --interval 0 0 + run_timeout 20 flux ping --pad 10240 --count 1024 --batch --interval 0 0 ' test_expect_success 'ping --rank 1 works' ' From 9f359d98d0fc978c55f4a68b0c22b294e42b1b63 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 8 Feb 2017 22:58:04 +0000 Subject: [PATCH 09/13] modules/wreck: fix inconsitent \n use in wlog_fatal Problem: wlog_fatal() sends log messages to flux_log() or vfprintf (stderr, ...) depending on context. The former takes messages without newlines; the latter requires a newline. Append a newline character to the stderr stream when that mode is selected. Drop trailing newlines from a couple of wlog_fatal() calls to be consistent with the majority of other calls. --- src/modules/wreck/wrexecd.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/modules/wreck/wrexecd.c b/src/modules/wreck/wrexecd.c index e05e0d545b7a..0817c5a41d8e 100644 --- a/src/modules/wreck/wrexecd.c +++ b/src/modules/wreck/wrexecd.c @@ -247,8 +247,10 @@ static void wlog_fatal (struct prog_ctx *ctx, int code, const char *format, ...) va_start (ap, format); if ((ctx != NULL) && ((c = prog_ctx_flux_handle (ctx)) != NULL)) flux_vlog (c, LOG_EMERG, format, ap); - else + else { vfprintf (stderr, format, ap); + putc ('\n', stderr); + } va_end (ap); /* Copy error to kvs if we're not in task context: @@ -390,7 +392,7 @@ static void wreck_pmi_line (struct task_info *t, const char *line) struct prog_ctx *ctx = t->ctx; int rc; if ((rc = pmi_simple_server_request (ctx->pmi, line, t)) < 0) - wlog_fatal (ctx, 1, "pmi_simple_server_request: %s\n", + wlog_fatal (ctx, 1, "pmi_simple_server_request: %s", strerror (errno)); if (rc == 1) wreck_pmi_close (t); @@ -2303,7 +2305,7 @@ int prog_ctx_get_id (struct prog_ctx *ctx, optparse_t *p) char *end; if (!optparse_getopt (p, "kvs-path", &kvspath)) - wlog_fatal (ctx, 1, "Required arg --kvs-path missing\n"); + wlog_fatal (ctx, 1, "Required arg --kvs-path missing"); ctx->kvspath = strdup (kvspath); if (!optparse_getopt (p, "lwj-id", &id)) { From 099807398003c95916007b22ec6259d3991d069e Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Fri, 31 Mar 2017 09:12:55 -0700 Subject: [PATCH 10/13] libutil/log: fix up zmq_strerror() message Problem: zeromq-4.2.1 reports EHOSTUNREACH as "Host unreachable", but "No route to host" is canonical on Linux and we have some tests that depend on it, so remap here. --- src/common/libutil/log.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/common/libutil/log.c b/src/common/libutil/log.c index 3b0e81e1ed2f..05548cd46649 100644 --- a/src/common/libutil/log.c +++ b/src/common/libutil/log.c @@ -62,7 +62,16 @@ _verr (int errnum, const char *fmt, va_list ap) { char *msg = NULL; char buf[128]; - const char *s = zmq_strerror (errnum); + const char *s; + + /* zeromq-4.2.1 reports EHOSTUNREACH as "Host unreachable", + * but "No route to host" is canonical on Linux and we have some + * tests that depend on it, so remap here. + */ + if (errnum == EHOSTUNREACH) + s = "No route to host"; + else + s = zmq_strerror (errnum); if (!prog) log_init (NULL); From a5174c8abba7c395fe2cfb51e6b0b6f585fd8c2c Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Fri, 31 Mar 2017 09:13:57 -0700 Subject: [PATCH 11/13] libutil/flog: fix up zmq_strerror() message Problem: zeromq-4.2.1 reports EHOSTUNREACH as "Host unreachable", but "No route to host" is canonical on Linux and we have some tests that depend on it, so remap here. --- src/common/libflux/flog.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/common/libflux/flog.c b/src/common/libflux/flog.c index 94106ed2effc..c47eff5d49e0 100644 --- a/src/common/libflux/flog.c +++ b/src/common/libflux/flog.c @@ -96,6 +96,12 @@ void flux_log_set_redirect (flux_t *h, flux_log_f fun, void *arg) const char *flux_strerror (int errnum) { + /* zeromq-4.2.1 reports EHOSTUNREACH as "Host unreachable", + * but "No route to host" is canonical on Linux and we have some + * tests that depend on it, so remap here. + */ + if (errnum == EHOSTUNREACH) + return "No route to host"; return zmq_strerror (errnum); } From 1db0fb6e44d31b905685110fa42cc266dea96889 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Sat, 1 Apr 2017 16:27:42 -0700 Subject: [PATCH 12/13] modules/wreck: fix printf-style type mismatch Problem: on arm7l architecture, wrexecd behaves erratically. Add printf-style format attributes to internal varargs debugging functions to enable type checking, then fix a couple places where the format specifier (%lu) implied 32-bit on this architecture, but the argument was 64 bit. Also fix non-const format specifier warnings. --- src/modules/wreck/wrexecd.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/modules/wreck/wrexecd.c b/src/modules/wreck/wrexecd.c index 0817c5a41d8e..f7b438cc955b 100644 --- a/src/modules/wreck/wrexecd.c +++ b/src/modules/wreck/wrexecd.c @@ -149,6 +149,19 @@ struct prog_ctx { int prog_ctx_remove_completion_ref (struct prog_ctx *ctx, const char *fmt, ...); int prog_ctx_add_completion_ref (struct prog_ctx *ctx, const char *fmt, ...); +static void wlog_msg (struct prog_ctx *ctx, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +static void wlog_error_kvs (struct prog_ctx *ctx, int fatal, const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); +static void wlog_fatal (struct prog_ctx *ctx, int code, const char *format, ...) + __attribute__ ((format (printf, 3, 4))); +static int wlog_err (struct prog_ctx *ctx, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +static void wlog_msg (struct prog_ctx *ctx, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +static void wlog_debug (struct prog_ctx *ctx, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + void *lsd_nomem_error (const char *file, int line, char *msg) { @@ -180,15 +193,13 @@ static flux_t *prog_ctx_flux_handle (struct prog_ctx *ctx) return (t->f); } -static void wlog_msg (struct prog_ctx *ctx, const char *fmt, ...); - static int archive_lwj (struct prog_ctx *ctx) { char *to = ctx->kvspath; char *link = NULL; int rc = -1; - wlog_msg (ctx, "archiving lwj %lu", ctx->id); + wlog_msg (ctx, "archiving lwj %" PRIi64, ctx->id); if (asprintf (&link, "lwj-complete.%d.%"PRId64, ctx->epoch, ctx->id) < 0) { flux_log_error (ctx->flux, "archive_lwj: asprintf"); @@ -967,7 +978,7 @@ int prog_ctx_load_lwj_info (struct prog_ctx *ctx) wlog_fatal (ctx, 1, "Failed to get resources for this node"); } else if (kvsdir_get_int (ctx->kvs, "tasks-per-node", &ctx->nprocs) < 0) - ctx->nprocs = 1; + ctx->nprocs = 1; if (ctx->nprocs <= 0) { wlog_fatal (ctx, 0, @@ -978,7 +989,7 @@ int prog_ctx_load_lwj_info (struct prog_ctx *ctx) for (i = 0; i < ctx->nprocs; i++) ctx->task[i] = task_info_create (ctx, i); - wlog_msg (ctx, "lwj %ld: node%d: nprocs=%d, nnodes=%d, cmdline=%s", + wlog_msg (ctx, "lwj %" PRIi64 ": node%d: nprocs=%d, nnodes=%d, cmdline=%s", ctx->id, ctx->nodeid, ctx->nprocs, ctx->nnodes, json_object_to_json_string (v)); free (json_str); @@ -1647,7 +1658,7 @@ static int l_wreck_log_msg (lua_State *L) return (2); /* error on stack from l_format_args */ if (!(msg = lua_tostring (L, 2))) return lua_pusherror (L, "required arg to log_msg missing"); - wlog_msg (ctx, msg); + wlog_msg (ctx, "%s", msg); return (0); } @@ -1659,7 +1670,7 @@ static int wreck_log_error (lua_State *L, int fatal) return (2); /* error on stack from l_format_args */ if (!(s = lua_tostring (L, 2))) return lua_pusherror (L, "required arg to die missing"); - wlog_error_kvs (ctx, fatal, s); + wlog_error_kvs (ctx, fatal, "%s", s); return (0); } @@ -2097,7 +2108,7 @@ void ev_cb (flux_t *f, flux_msg_handler_t *mw, int sig = 9; if (json_object_object_get_ex (o, "signal", &ox)) sig = json_object_get_int (ox); - wlog_msg (ctx, "Killing jobid %lu with signal %d", ctx->id, sig); + wlog_msg (ctx, "Killing jobid %" PRIi64 " with signal %d", ctx->id, sig); prog_ctx_signal (ctx, sig); } json_object_put (o); From 62fdb65d1e04ff59b646820d4922f9318c256b9e Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Sat, 1 Apr 2017 21:15:45 -0700 Subject: [PATCH 13/13] broker/content-cache: fix error path NULL deref Due to a typo in which variables were interchanged, an error handling code path in cache_store_continuation() could trigger a SEGFAULT on arm7l test system. Fix the typo. --- src/broker/content-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/broker/content-cache.c b/src/broker/content-cache.c index de16e5e9c265..7d6774182c01 100644 --- a/src/broker/content-cache.c +++ b/src/broker/content-cache.c @@ -450,7 +450,7 @@ static void cache_store_continuation (flux_rpc_t *rpc, void *arg) done: if (respond_requests_raw (&e->store_requests, cache->h, rc < 0 ? saved_errno : 0, - e->blobref, strlen (blobref) + 1) < 0) + e->blobref, strlen (e->blobref) + 1) < 0) flux_log_error (cache->h, "%s: error responding to store requests", __FUNCTION__); flux_rpc_destroy (rpc);