1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

fdstream: Emit stream abort callback even if poll() doesnt.

This patch causes the fdstream driver to call the stream event callback
if virStreamAbort() is called on a stream using this driver.

A remote handler for a stream can only detect changes via stream events,
so this event callback is necessary in order to enable a daemon to abort
a stream in such a way that the client will see the change.

* src/fdstream.c:
        - modify close function to call stream event callback
This commit is contained in:
Peter Krempa 2012-02-23 12:54:18 +01:00
parent afa4336e94
commit 95fdc1bc2b

View File

@ -1,7 +1,7 @@
/* /*
* fdstream.h: generic streams impl for file descriptors * fdstream.c: generic streams impl for file descriptors
* *
* Copyright (C) 2009-2011 Red Hat, Inc. * Copyright (C) 2009-2012 Red Hat, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -55,6 +55,7 @@ struct virFDStreamData {
unsigned long long length; unsigned long long length;
int watch; int watch;
int events; /* events the stream callback is subscribed for */
bool cbRemoved; bool cbRemoved;
bool dispatching; bool dispatching;
bool closed; bool closed;
@ -62,6 +63,10 @@ struct virFDStreamData {
void *opaque; void *opaque;
virFreeCallback ff; virFreeCallback ff;
/* don't call the abort callback more than once */
bool abortCallbackCalled;
bool abortCallbackDispatching;
virMutex lock; virMutex lock;
}; };
@ -92,6 +97,7 @@ static int virFDStreamRemoveCallback(virStreamPtr stream)
fdst->watch = 0; fdst->watch = 0;
fdst->ff = NULL; fdst->ff = NULL;
fdst->cb = NULL; fdst->cb = NULL;
fdst->events = 0;
fdst->opaque = NULL; fdst->opaque = NULL;
ret = 0; ret = 0;
@ -120,6 +126,7 @@ static int virFDStreamUpdateCallback(virStreamPtr stream, int events)
} }
virEventUpdateHandle(fdst->watch, events); virEventUpdateHandle(fdst->watch, events);
fdst->events = events;
ret = 0; ret = 0;
@ -214,6 +221,8 @@ virFDStreamAddCallback(virStreamPtr st,
fdst->cb = cb; fdst->cb = cb;
fdst->opaque = opaque; fdst->opaque = opaque;
fdst->ff = ff; fdst->ff = ff;
fdst->events = events;
fdst->abortCallbackCalled = false;
virStreamRef(st); virStreamRef(st);
ret = 0; ret = 0;
@ -225,18 +234,48 @@ cleanup:
static int static int
virFDStreamClose(virStreamPtr st) virFDStreamCloseInt(virStreamPtr st, bool streamAbort)
{ {
struct virFDStreamData *fdst = st->privateData; struct virFDStreamData *fdst;
virStreamEventCallback cb;
void *opaque;
int ret; int ret;
VIR_DEBUG("st=%p", st); VIR_DEBUG("st=%p", st);
if (!fdst) if (!st || !(fdst = st->privateData) || fdst->abortCallbackDispatching)
return 0; return 0;
virMutexLock(&fdst->lock); virMutexLock(&fdst->lock);
/* aborting the stream, ensure the callback is called if it's
* registered for stream error event */
if (streamAbort &&
fdst->cb &&
(fdst->events & (VIR_STREAM_EVENT_READABLE |
VIR_STREAM_EVENT_WRITABLE))) {
/* don't enter this function accidentally from the callback again */
if (fdst->abortCallbackCalled) {
virMutexUnlock(&fdst->lock);
return 0;
}
fdst->abortCallbackCalled = true;
fdst->abortCallbackDispatching = true;
/* cache the pointers */
cb = fdst->cb;
opaque = fdst->opaque;
virMutexUnlock(&fdst->lock);
/* call failure callback, poll reports nothing on closed fd */
(cb)(st, VIR_STREAM_EVENT_ERROR, opaque);
virMutexLock(&fdst->lock);
fdst->abortCallbackDispatching = false;
}
/* mutex locked */
ret = VIR_CLOSE(fdst->fd); ret = VIR_CLOSE(fdst->fd);
if (fdst->cmd) { if (fdst->cmd) {
char buf[1024]; char buf[1024];
@ -286,6 +325,18 @@ virFDStreamClose(virStreamPtr st)
return ret; return ret;
} }
static int
virFDStreamClose(virStreamPtr st)
{
return virFDStreamCloseInt(st, false);
}
static int
virFDStreamAbort(virStreamPtr st)
{
return virFDStreamCloseInt(st, true);
}
static int virFDStreamWrite(virStreamPtr st, const char *bytes, size_t nbytes) static int virFDStreamWrite(virStreamPtr st, const char *bytes, size_t nbytes)
{ {
struct virFDStreamData *fdst = st->privateData; struct virFDStreamData *fdst = st->privateData;
@ -392,7 +443,7 @@ static virStreamDriver virFDStreamDrv = {
.streamSend = virFDStreamWrite, .streamSend = virFDStreamWrite,
.streamRecv = virFDStreamRead, .streamRecv = virFDStreamRead,
.streamFinish = virFDStreamClose, .streamFinish = virFDStreamClose,
.streamAbort = virFDStreamClose, .streamAbort = virFDStreamAbort,
.streamAddCallback = virFDStreamAddCallback, .streamAddCallback = virFDStreamAddCallback,
.streamUpdateCallback = virFDStreamUpdateCallback, .streamUpdateCallback = virFDStreamUpdateCallback,
.streamRemoveCallback = virFDStreamRemoveCallback .streamRemoveCallback = virFDStreamRemoveCallback