libxl__ev_time_deregister(gc, &aes->time);
if (status) {
- libxl_report_child_exitstatus(CTX, LIBXL__LOG_ERROR,
- aes->what, pid, status);
+ if (!aes->rc)
+ libxl_report_child_exitstatus(CTX, LIBXL__LOG_ERROR,
+ aes->what, pid, status);
}
- aes->callback(egc, aes, status);
+ aes->callback(egc, aes, aes->rc, status);
}
void libxl__async_exec_init(libxl__async_exec_state *aes)
libxl__ev_child *const child = &aes->child;
char ** const args = aes->args;
+ aes->rc = 0;
+
/* Set execution timeout */
if (libxl__ev_time_register_rel(ao, &aes->time,
async_exec_timeout,
static void device_hotplug_child_death_cb(libxl__egc *egc,
libxl__async_exec_state *aes,
- int status);
+ int rc, int status);
static void device_destroy_be_watch_cb(libxl__egc *egc,
libxl__xswait_state *xswait,
static void device_hotplug_child_death_cb(libxl__egc *egc,
libxl__async_exec_state *aes,
- int status)
+ int rc, int status)
{
libxl__ao_device *aodev = CONTAINER_OF(aes, *aodev, aes);
STATE_AO_GC(aodev->ao);
device_hotplug_clean(gc, aodev);
- if (status) {
+ if (status && !rc) {
hotplug_error = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/hotplug-error", be_path));
if (hotplug_error)
LOG(ERROR, "script: %s", hotplug_error);
- aodev->rc = ERROR_FAIL;
+ rc = ERROR_FAIL;
+ }
+
+ if (rc) {
+ if (!aodev->rc)
+ aodev->rc = rc;
if (aodev->action == LIBXL__DEVICE_ACTION_ADD)
/*
* Only fail on device connection, on disconnection
typedef struct libxl__async_exec_state libxl__async_exec_state;
typedef void libxl__async_exec_callback(libxl__egc *egc,
- libxl__async_exec_state *aes, int status);
+ libxl__async_exec_state *aes, int rc, int status);
+/*
+ * Meaning of status and rc:
+ * rc==0, status==0 all went well
+ * rc==0, status!=0 everything OK except child exited nonzero (logged)
+ * rc!=0 something else went wrong (status is real
+ * exit status; maybe reflecting SIGKILL, and
+ * therefore not very interesting, if aes code
+ * killed the child). Logged unless ABORTED.
+ */
struct libxl__async_exec_state {
/* caller must fill these in */
/* private */
libxl__ev_time time;
libxl__ev_child child;
+ int rc;
};
void libxl__async_exec_init(libxl__async_exec_state *aes);
static void netbuf_setup_script_cb(libxl__egc *egc,
libxl__async_exec_state *aes,
- int status);
+ int rc, int status);
static void netbuf_teardown_script_cb(libxl__egc *egc,
libxl__async_exec_state *aes,
- int status);
+ int rc, int status);
/*
* the script needs the following env & args
*/
static void netbuf_setup_script_cb(libxl__egc *egc,
libxl__async_exec_state *aes,
- int status)
+ int rc, int status)
{
libxl__ao_device *aodev = CONTAINER_OF(aes, *aodev, aes);
libxl__remus_device *dev = CONTAINER_OF(aodev, *dev, aodev);
libxl__remus_device_nic *remus_nic = dev->concrete_data;
libxl__remus_devices_state *rds = dev->rds;
const char *out_path_base, *hotplug_error = NULL;
- int rc;
STATE_AO_GC(rds->ao);
const char *const vif = remus_nic->vif;
const char **const ifb = &remus_nic->ifb;
+ if (status && !rc)
+ rc = ERROR_FAIL;
+ if (rc)
+ goto out;
+
/*
* we need to get ifb first because it's needed for teardown
*/
static void netbuf_teardown_script_cb(libxl__egc *egc,
libxl__async_exec_state *aes,
- int status)
+ int rc, int status)
{
- int rc;
libxl__ao_device *aodev = CONTAINER_OF(aes, *aodev, aes);
libxl__remus_device *dev = CONTAINER_OF(aodev, *dev, aodev);
libxl__remus_device_nic *remus_nic = dev->concrete_data;
- if (status)
+ if (status && !rc)
rc = ERROR_FAIL;
- else
- rc = 0;
free_qdisc(remus_nic);
/* callbacks */
static void match_async_exec_cb(libxl__egc *egc,
libxl__async_exec_state *aes,
- int status);
+ int rc, int status);
/* implementations */
static void match_async_exec_cb(libxl__egc *egc,
libxl__async_exec_state *aes,
- int status)
+ int rc, int status)
{
- int rc;
libxl__ao_device *aodev = CONTAINER_OF(aes, *aodev, aes);
libxl__remus_device *dev = CONTAINER_OF(aodev, *dev, aodev);
libxl__remus_drbd_disk *drbd_disk;
STATE_AO_GC(aodev->ao);
+ if (rc)
+ goto out;
+
if (status) {
rc = ERROR_REMUS_DEVOPS_DOES_NOT_MATCH;
/* BUG: seems to assume that any exit status means `no match' */