If a callback being invoked from a stream issues a virStreamAbort operation, the stream data will be free'd but the callback will then stil 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 --- src/fdstream.c | 33 +++++++++++++++++++++++---------- 1 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/fdstream.c b/src/fdstream.c index c1ad787..182b6fa 100644 --- a/src/fdstream.c +++ b/src/fdstream.c @@ -56,8 +56,9 @@ struct virFDStreamData { unsigned long long length; int watch; - unsigned int cbRemoved; - unsigned int dispatching; + bool cbRemoved; + bool dispatching; + bool closed; virStreamEventCallback cb; void *opaque; virFreeCallback ff; @@ -85,7 +86,7 @@ static int virFDStreamRemoveCallback(virStreamPtr stream) virEventRemoveHandle(fdst->watch); if (fdst->dispatching) - fdst->cbRemoved = 1; + fdst->cbRemoved = true; else if (fdst->ff) (fdst->ff)(fdst->opaque); @@ -138,6 +139,7 @@ static void virFDStreamEvent(int watch ATTRIBUTE_UNUSED, virStreamEventCallback cb; void *cbopaque; virFreeCallback ff; + bool closed; if (!fdst) return; @@ -151,16 +153,22 @@ static void virFDStreamEvent(int watch ATTRIBUTE_UNUSED, cb = fdst->cb; cbopaque = fdst->opaque; ff = fdst->ff; - fdst->dispatching = 1; + fdst->dispatching = true; virMutexUnlock(&fdst->lock); cb(stream, events, cbopaque); virMutexLock(&fdst->lock); - fdst->dispatching = 0; + fdst->dispatching = false; if (fdst->cbRemoved && ff) (ff)(cbopaque); + closed = fdst->closed; virMutexUnlock(&fdst->lock); + + if (closed) { + virMutexDestroy(&fdst->lock); + VIR_FREE(fdst); + } } static int @@ -196,7 +204,7 @@ virFDStreamAddCallback(virStreamPtr st, goto cleanup; } - fdst->cbRemoved = 0; + fdst->cbRemoved = false; fdst->cb = cb; fdst->opaque = opaque; fdst->ff = ff; @@ -252,13 +260,18 @@ virFDStreamClose(virStreamPtr st) ret = -1; } virCommandFree(fdst->cmd); + fdst->cmd = NULL; } - st->privateData = NULL; - virMutexUnlock(&fdst->lock); - virMutexDestroy(&fdst->lock); - VIR_FREE(fdst); + if (fdst->dispatching) { + fdst->closed = true; + virMutexUnlock(&fdst->lock); + } else { + virMutexUnlock(&fdst->lock); + virMutexDestroy(&fdst->lock); + VIR_FREE(fdst); + } return ret; } -- 1.7.4.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list