* @conn: pointer to the connection
* @cbList: the list
* @callback: the callback to remove
+ * @doFreeCb: Inhibit calling the freecb
*
* Internal function to remove a callback from a virObjectEventCallbackListPtr
*/
static int
virObjectEventCallbackListRemoveID(virConnectPtr conn,
virObjectEventCallbackListPtr cbList,
- int callbackID)
+ int callbackID,
+ bool doFreeCb)
{
size_t i;
cb->key_filter ? cb->key : NULL,
cb->remoteID >= 0) - 1);
- if (cb->freecb)
+ /* @doFreeCb inhibits calling @freecb from error paths in
+ * register functions to ensure the caller of a failed register
+ * function won't end up with a double free error */
+ if (doFreeCb && cb->freecb)
(*cb->freecb)(cb->opaque);
virObjectEventCallbackFree(cb);
VIR_DELETE_ELEMENT(cbList->callbacks, i, cbList->count);
* @conn: connection to associate with callback
* @state: object event state
* @callbackID: ID of the function to remove from event
+ * @doFreeCb: Allow the calling of a freecb
*
* Unregister the function @callbackID with connection @conn,
- * from @state, for events.
+ * from @state, for events. If @doFreeCb is false, then we
+ * are being called from a remote call failure path for the
+ * Event registration indicating a -1 return to the caller. The
+ * caller wouldn't expect us to run their freecb function if it
+ * exists, so we cannot do so.
*
* Returns: the number of callbacks still registered, or -1 on error
*/
int
virObjectEventStateDeregisterID(virConnectPtr conn,
virObjectEventStatePtr state,
- int callbackID)
+ int callbackID,
+ bool doFreeCb)
{
int ret;
state->callbacks,
callbackID);
else
- ret = virObjectEventCallbackListRemoveID(conn,
- state->callbacks, callbackID);
+ ret = virObjectEventCallbackListRemoveID(conn, state->callbacks,
+ callbackID, doFreeCb);
virObjectEventStateCleanupTimer(state, true);
(xdrproc_t) xdr_remote_connect_network_event_register_any_args, (char *) &args,
(xdrproc_t) xdr_remote_connect_network_event_register_any_ret, (char *) &ret) == -1) {
virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID);
+ callbackID, false);
goto done;
}
virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
goto done;
if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID)) < 0)
+ callbackID, true)) < 0)
goto done;
/* If that was the last callback for this eventID, we need to disable
(xdrproc_t) xdr_remote_connect_storage_pool_event_register_any_args, (char *) &args,
(xdrproc_t) xdr_remote_connect_storage_pool_event_register_any_ret, (char *) &ret) == -1) {
virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID);
+ callbackID, false);
goto done;
}
goto done;
if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID)) < 0)
+ callbackID, true)) < 0)
goto done;
/* If that was the last callback for this eventID, we need to disable
(xdrproc_t) xdr_remote_connect_node_device_event_register_any_args, (char *) &args,
(xdrproc_t) xdr_remote_connect_node_device_event_register_any_ret, (char *) &ret) == -1) {
virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID);
+ callbackID, false);
goto done;
}
goto done;
if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID)) < 0)
+ callbackID, true)) < 0)
goto done;
/* If that was the last callback for this eventID, we need to disable
(xdrproc_t) xdr_remote_connect_secret_event_register_any_args, (char *) &args,
(xdrproc_t) xdr_remote_connect_secret_event_register_any_ret, (char *) &ret) == -1) {
virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID);
+ callbackID, false);
goto done;
}
goto done;
if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID)) < 0)
+ callbackID, true)) < 0)
goto done;
/* If that was the last callback for this eventID, we need to disable
(xdrproc_t) xdr_qemu_connect_domain_monitor_event_register_args, (char *) &args,
(xdrproc_t) xdr_qemu_connect_domain_monitor_event_register_ret, (char *) &ret) == -1) {
virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID);
+ callbackID, false);
goto done;
}
virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
goto done;
if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID)) < 0)
+ callbackID, true)) < 0)
goto done;
/* If that was the last callback for this event, we need to disable
(xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_args, (char *) &args,
(xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_ret, (char *) &ret) == -1) {
virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID);
+ callbackID, false);
goto done;
}
virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
(xdrproc_t) xdr_void, (char *) NULL,
(xdrproc_t) xdr_void, (char *) NULL) == -1) {
virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID);
+ callbackID, false);
goto done;
}
}
goto done;
if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID)) < 0)
+ callbackID, true)) < 0)
goto done;
if (count == 0) {
(xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_args, (char *) &args,
(xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_ret, (char *) &ret) == -1) {
virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID);
+ callbackID, false);
goto done;
}
virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
(xdrproc_t) xdr_remote_connect_domain_event_register_any_args, (char *) &args,
(xdrproc_t) xdr_void, (char *)NULL) == -1) {
virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID);
+ callbackID, false);
goto done;
}
}
goto done;
if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
- callbackID)) < 0)
+ callbackID, true)) < 0)
goto done;
/* If that was the last callback for this eventID, we need to disable