mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-24 21:45:21 +00:00
Use a virFreeCallback on virNetSocket to ensure safe release
When unregistering an I/O callback from a virNetSocket object, there is still a chance that an event may come in on the callback. In this case it is possible that the virNetSocket might have been freed already. Make use of a virFreeCallback when registering the I/O callbacks and hold a reference for the entire time the callback is set. * src/rpc/virnetsocket.c: Register a free function for the file handle watch * src/rpc/virnetsocket.h, src/rpc/virnetserverservice.c, src/rpc/virnetserverclient.c, src/rpc/virnetclient.c: Add a free function for the socket I/O watches
This commit is contained in:
parent
6198f3a1d7
commit
7ea2ef4ce8
@ -110,6 +110,13 @@ static void virNetClientIncomingEvent(virNetSocketPtr sock,
|
|||||||
int events,
|
int events,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
|
static void virNetClientEventFree(void *opaque)
|
||||||
|
{
|
||||||
|
virNetClientPtr client = opaque;
|
||||||
|
|
||||||
|
virNetClientFree(client);
|
||||||
|
}
|
||||||
|
|
||||||
static virNetClientPtr virNetClientNew(virNetSocketPtr sock,
|
static virNetClientPtr virNetClientNew(virNetSocketPtr sock,
|
||||||
const char *hostname)
|
const char *hostname)
|
||||||
{
|
{
|
||||||
@ -140,11 +147,15 @@ static virNetClientPtr virNetClientNew(virNetSocketPtr sock,
|
|||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
/* Set up a callback to listen on the socket data */
|
/* Set up a callback to listen on the socket data */
|
||||||
|
client->refs++;
|
||||||
if (virNetSocketAddIOCallback(client->sock,
|
if (virNetSocketAddIOCallback(client->sock,
|
||||||
VIR_EVENT_HANDLE_READABLE,
|
VIR_EVENT_HANDLE_READABLE,
|
||||||
virNetClientIncomingEvent,
|
virNetClientIncomingEvent,
|
||||||
client) < 0)
|
client,
|
||||||
|
virNetClientEventFree) < 0) {
|
||||||
|
client->refs--;
|
||||||
VIR_DEBUG("Failed to add event watch, disabling events");
|
VIR_DEBUG("Failed to add event watch, disabling events");
|
||||||
|
}
|
||||||
|
|
||||||
VIR_DEBUG("client=%p refs=%d", client, client->refs);
|
VIR_DEBUG("client=%p refs=%d", client, client->refs);
|
||||||
return client;
|
return client;
|
||||||
|
@ -160,6 +160,13 @@ virNetServerClientCalculateHandleMode(virNetServerClientPtr client) {
|
|||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void virNetServerClientEventFree(void *opaque)
|
||||||
|
{
|
||||||
|
virNetServerClientPtr client = opaque;
|
||||||
|
|
||||||
|
virNetServerClientFree(client);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @server: a locked or unlocked server object
|
* @server: a locked or unlocked server object
|
||||||
* @client: a locked client object
|
* @client: a locked client object
|
||||||
@ -168,12 +175,16 @@ static int virNetServerClientRegisterEvent(virNetServerClientPtr client)
|
|||||||
{
|
{
|
||||||
int mode = virNetServerClientCalculateHandleMode(client);
|
int mode = virNetServerClientCalculateHandleMode(client);
|
||||||
|
|
||||||
|
client->refs++;
|
||||||
VIR_DEBUG("Registering client event callback %d", mode);
|
VIR_DEBUG("Registering client event callback %d", mode);
|
||||||
if (virNetSocketAddIOCallback(client->sock,
|
if (virNetSocketAddIOCallback(client->sock,
|
||||||
mode,
|
mode,
|
||||||
virNetServerClientDispatchEvent,
|
virNetServerClientDispatchEvent,
|
||||||
client) < 0)
|
client,
|
||||||
|
virNetServerClientEventFree) < 0) {
|
||||||
|
client->refs--;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,14 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void virNetServerServiceEventFree(void *opaque)
|
||||||
|
{
|
||||||
|
virNetServerServicePtr svc = opaque;
|
||||||
|
|
||||||
|
virNetServerServiceFree(svc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename,
|
virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename,
|
||||||
const char *service,
|
const char *service,
|
||||||
int auth,
|
int auth,
|
||||||
@ -124,12 +132,16 @@ virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename,
|
|||||||
|
|
||||||
/* IO callback is initially disabled, until we're ready
|
/* IO callback is initially disabled, until we're ready
|
||||||
* to deal with incoming clients */
|
* to deal with incoming clients */
|
||||||
|
virNetServerServiceRef(svc);
|
||||||
if (virNetSocketAddIOCallback(svc->socks[i],
|
if (virNetSocketAddIOCallback(svc->socks[i],
|
||||||
0,
|
0,
|
||||||
virNetServerServiceAccept,
|
virNetServerServiceAccept,
|
||||||
svc) < 0)
|
svc,
|
||||||
|
virNetServerServiceEventFree) < 0) {
|
||||||
|
virNetServerServiceFree(svc);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return svc;
|
return svc;
|
||||||
@ -180,12 +192,16 @@ virNetServerServicePtr virNetServerServiceNewUNIX(const char *path,
|
|||||||
|
|
||||||
/* IO callback is initially disabled, until we're ready
|
/* IO callback is initially disabled, until we're ready
|
||||||
* to deal with incoming clients */
|
* to deal with incoming clients */
|
||||||
|
virNetServerServiceRef(svc);
|
||||||
if (virNetSocketAddIOCallback(svc->socks[i],
|
if (virNetSocketAddIOCallback(svc->socks[i],
|
||||||
0,
|
0,
|
||||||
virNetServerServiceAccept,
|
virNetServerServiceAccept,
|
||||||
svc) < 0)
|
svc,
|
||||||
|
virNetServerServiceEventFree) < 0) {
|
||||||
|
virNetServerServiceFree(svc);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return svc;
|
return svc;
|
||||||
|
@ -58,8 +58,12 @@ struct _virNetSocket {
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int errfd;
|
int errfd;
|
||||||
bool client;
|
bool client;
|
||||||
|
|
||||||
|
/* Event callback fields */
|
||||||
virNetSocketIOFunc func;
|
virNetSocketIOFunc func;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
|
virFreeCallback ff;
|
||||||
|
|
||||||
virSocketAddr localAddr;
|
virSocketAddr localAddr;
|
||||||
virSocketAddr remoteAddr;
|
virSocketAddr remoteAddr;
|
||||||
char *localAddrStr;
|
char *localAddrStr;
|
||||||
@ -1121,10 +1125,31 @@ static void virNetSocketEventHandle(int watch ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void virNetSocketEventFree(void *opaque)
|
||||||
|
{
|
||||||
|
virNetSocketPtr sock = opaque;
|
||||||
|
virFreeCallback ff;
|
||||||
|
void *eopaque;
|
||||||
|
|
||||||
|
virMutexLock(&sock->lock);
|
||||||
|
ff = sock->ff;
|
||||||
|
eopaque = sock->opaque;
|
||||||
|
sock->func = NULL;
|
||||||
|
sock->ff = NULL;
|
||||||
|
sock->opaque = NULL;
|
||||||
|
virMutexUnlock(&sock->lock);
|
||||||
|
|
||||||
|
if (ff)
|
||||||
|
ff(eopaque);
|
||||||
|
|
||||||
|
virNetSocketFree(sock);
|
||||||
|
}
|
||||||
|
|
||||||
int virNetSocketAddIOCallback(virNetSocketPtr sock,
|
int virNetSocketAddIOCallback(virNetSocketPtr sock,
|
||||||
int events,
|
int events,
|
||||||
virNetSocketIOFunc func,
|
virNetSocketIOFunc func,
|
||||||
void *opaque)
|
void *opaque,
|
||||||
|
virFreeCallback ff)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
@ -1134,16 +1159,19 @@ int virNetSocketAddIOCallback(virNetSocketPtr sock,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sock->refs++;
|
||||||
if ((sock->watch = virEventAddHandle(sock->fd,
|
if ((sock->watch = virEventAddHandle(sock->fd,
|
||||||
events,
|
events,
|
||||||
virNetSocketEventHandle,
|
virNetSocketEventHandle,
|
||||||
sock,
|
sock,
|
||||||
NULL)) < 0) {
|
virNetSocketEventFree)) < 0) {
|
||||||
VIR_DEBUG("Failed to register watch on socket %p", sock);
|
VIR_DEBUG("Failed to register watch on socket %p", sock);
|
||||||
|
sock->refs--;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
sock->func = func;
|
sock->func = func;
|
||||||
sock->opaque = opaque;
|
sock->opaque = opaque;
|
||||||
|
sock->ff = ff;
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
@ -109,7 +109,8 @@ int virNetSocketAccept(virNetSocketPtr sock,
|
|||||||
int virNetSocketAddIOCallback(virNetSocketPtr sock,
|
int virNetSocketAddIOCallback(virNetSocketPtr sock,
|
||||||
int events,
|
int events,
|
||||||
virNetSocketIOFunc func,
|
virNetSocketIOFunc func,
|
||||||
void *opaque);
|
void *opaque,
|
||||||
|
virFreeCallback ff);
|
||||||
|
|
||||||
void virNetSocketUpdateIOCallback(virNetSocketPtr sock,
|
void virNetSocketUpdateIOCallback(virNetSocketPtr sock,
|
||||||
int events);
|
int events);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user