mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
Fix crash when aborting a stream from a I/O callback
If a callback being invoked from a stream issues a virStreamAbort operation, the stream data will be free'd but the callback will then still try to use this. Delay free'ing of the stream data when a callback is dispatching * src/fdstream.c: Delay stream free when callback is active
This commit is contained in:
parent
c72aecc5fc
commit
d97093437f
@ -56,8 +56,9 @@ struct virFDStreamData {
|
|||||||
unsigned long long length;
|
unsigned long long length;
|
||||||
|
|
||||||
int watch;
|
int watch;
|
||||||
unsigned int cbRemoved;
|
bool cbRemoved;
|
||||||
unsigned int dispatching;
|
bool dispatching;
|
||||||
|
bool closed;
|
||||||
virStreamEventCallback cb;
|
virStreamEventCallback cb;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
virFreeCallback ff;
|
virFreeCallback ff;
|
||||||
@ -85,7 +86,7 @@ static int virFDStreamRemoveCallback(virStreamPtr stream)
|
|||||||
|
|
||||||
virEventRemoveHandle(fdst->watch);
|
virEventRemoveHandle(fdst->watch);
|
||||||
if (fdst->dispatching)
|
if (fdst->dispatching)
|
||||||
fdst->cbRemoved = 1;
|
fdst->cbRemoved = true;
|
||||||
else if (fdst->ff)
|
else if (fdst->ff)
|
||||||
(fdst->ff)(fdst->opaque);
|
(fdst->ff)(fdst->opaque);
|
||||||
|
|
||||||
@ -138,6 +139,7 @@ static void virFDStreamEvent(int watch ATTRIBUTE_UNUSED,
|
|||||||
virStreamEventCallback cb;
|
virStreamEventCallback cb;
|
||||||
void *cbopaque;
|
void *cbopaque;
|
||||||
virFreeCallback ff;
|
virFreeCallback ff;
|
||||||
|
bool closed;
|
||||||
|
|
||||||
if (!fdst)
|
if (!fdst)
|
||||||
return;
|
return;
|
||||||
@ -151,16 +153,22 @@ static void virFDStreamEvent(int watch ATTRIBUTE_UNUSED,
|
|||||||
cb = fdst->cb;
|
cb = fdst->cb;
|
||||||
cbopaque = fdst->opaque;
|
cbopaque = fdst->opaque;
|
||||||
ff = fdst->ff;
|
ff = fdst->ff;
|
||||||
fdst->dispatching = 1;
|
fdst->dispatching = true;
|
||||||
virMutexUnlock(&fdst->lock);
|
virMutexUnlock(&fdst->lock);
|
||||||
|
|
||||||
cb(stream, events, cbopaque);
|
cb(stream, events, cbopaque);
|
||||||
|
|
||||||
virMutexLock(&fdst->lock);
|
virMutexLock(&fdst->lock);
|
||||||
fdst->dispatching = 0;
|
fdst->dispatching = false;
|
||||||
if (fdst->cbRemoved && ff)
|
if (fdst->cbRemoved && ff)
|
||||||
(ff)(cbopaque);
|
(ff)(cbopaque);
|
||||||
|
closed = fdst->closed;
|
||||||
virMutexUnlock(&fdst->lock);
|
virMutexUnlock(&fdst->lock);
|
||||||
|
|
||||||
|
if (closed) {
|
||||||
|
virMutexDestroy(&fdst->lock);
|
||||||
|
VIR_FREE(fdst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -196,7 +204,7 @@ virFDStreamAddCallback(virStreamPtr st,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
fdst->cbRemoved = 0;
|
fdst->cbRemoved = false;
|
||||||
fdst->cb = cb;
|
fdst->cb = cb;
|
||||||
fdst->opaque = opaque;
|
fdst->opaque = opaque;
|
||||||
fdst->ff = ff;
|
fdst->ff = ff;
|
||||||
@ -252,13 +260,18 @@ virFDStreamClose(virStreamPtr st)
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
virCommandFree(fdst->cmd);
|
virCommandFree(fdst->cmd);
|
||||||
|
fdst->cmd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
st->privateData = NULL;
|
st->privateData = NULL;
|
||||||
|
|
||||||
virMutexUnlock(&fdst->lock);
|
if (fdst->dispatching) {
|
||||||
virMutexDestroy(&fdst->lock);
|
fdst->closed = true;
|
||||||
VIR_FREE(fdst);
|
virMutexUnlock(&fdst->lock);
|
||||||
|
} else {
|
||||||
|
virMutexUnlock(&fdst->lock);
|
||||||
|
virMutexDestroy(&fdst->lock);
|
||||||
|
VIR_FREE(fdst);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user