spawn_detach(gc, ss);
}
+void libxl__spawn_initiate_failure(libxl__egc *egc, libxl__spawn_state *ss,
+ int rc)
+/* The spawn state must be Attached on entry and will be Attached Failed
+ * on return. */
+{
+ spawn_fail(egc, ss, rc);
+}
+
static void spawn_fail(libxl__egc *egc, libxl__spawn_state *ss, int rc)
/* Caller must have logged. Must be last thing in calling function,
* as it may make the callback. Precondition: Attached or Detaching. */
{
EGC_GC;
assert(rc);
- ss->rc = rc;
+ if (!ss->rc)
+ ss->rc = rc;
spawn_detach(gc, ss);
}
*
* The inner child must soon exit or exec. It must also soon exit or
* notify the parent of its successful startup by writing to the
- * xenstore path xspath.
+ * xenstore path xspath OR via other means that the parent will have
+ * to set up.
*
* The user (in the parent) will be called back (confirm_cb) every
* time that xenstore path is modified.
*/
_hidden void libxl__spawn_initiate_detach(libxl__gc *gc, libxl__spawn_state*);
+/*
+ * libxl__spawn_initiate_failure - Propagate failure from the caller to the
+ * callee.
+ *
+ * Works by killing the intermediate process from spawn_spawn.
+ * After this function returns, a failure will be reported.
+ *
+ * This is not synchronous: there will be a further callback when
+ * the detach is complete.
+ *
+ * Caller must have logged a failure reason.
+ *
+ * The spawn state must be Attached on entry and will remain Attached. It
+ * is possible for a spawn to fail for multiple reasons, for example
+ * call(s) to libxl__spawn_initiate_failure and also for some other reason.
+ * In that case the first rc value from any source will take precedence.
+ */
+_hidden void libxl__spawn_initiate_failure(libxl__egc *egc,
+ libxl__spawn_state *ss, int rc);
+
/*
* If successful, this should return 0.
*