提交 133c511b 编写于 作者: B Ben Gray 提交者: Martin Kletzander

rpc: Don't rewrite msg->fds on every read dispatch

When we are receiving data in smaller chunks it might happen that
virNetServerClientDispatchRead() will be called multiple times.  And as
that happens, if it is a message that also transfer headers, we decode
the number of them every single time and, unfortunately, also allocate
the memory for them.  That causes a leak, in the best scenario.

Best viewed with '-w'.
Signed-off-by: NMartin Kletzander <mkletzan@redhat.com>
上级 545e5571
...@@ -1107,36 +1107,38 @@ static void virNetServerClientDispatchRead(virNetServerClientPtr client) ...@@ -1107,36 +1107,38 @@ static void virNetServerClientDispatchRead(virNetServerClientPtr client)
/* Now figure out if we need to read more data to get some /* Now figure out if we need to read more data to get some
* file descriptors */ * file descriptors */
if (msg->header.type == VIR_NET_CALL_WITH_FDS && if (msg->header.type == VIR_NET_CALL_WITH_FDS) {
virNetMessageDecodeNumFDs(msg) < 0) { if (msg->nfds == 0 &&
virNetMessageQueueServe(&client->rx); virNetMessageDecodeNumFDs(msg) < 0) {
virNetMessageFree(msg);
client->wantClose = true;
return; /* Error */
}
/* Try getting the file descriptors (may fail if blocking) */
for (i = msg->donefds; i < msg->nfds; i++) {
int rv;
if ((rv = virNetSocketRecvFD(client->sock, &(msg->fds[i]))) < 0) {
virNetMessageQueueServe(&client->rx); virNetMessageQueueServe(&client->rx);
virNetMessageFree(msg); virNetMessageFree(msg);
client->wantClose = true; client->wantClose = true;
return; return; /* Error */
} }
if (rv == 0) /* Blocking */
break;
msg->donefds++;
}
/* Need to poll() until FDs arrive */ /* Try getting the file descriptors (may fail if blocking) */
if (msg->donefds < msg->nfds) { for (i = msg->donefds; i < msg->nfds; i++) {
/* Because DecodeHeader/NumFDs reset bufferOffset, we int rv;
* put it back to what it was, so everything works if ((rv = virNetSocketRecvFD(client->sock, &(msg->fds[i]))) < 0) {
* again next time we run this method virNetMessageQueueServe(&client->rx);
*/ virNetMessageFree(msg);
client->rx->bufferOffset = client->rx->bufferLength; client->wantClose = true;
return; return;
}
if (rv == 0) /* Blocking */
break;
msg->donefds++;
}
/* Need to poll() until FDs arrive */
if (msg->donefds < msg->nfds) {
/* Because DecodeHeader/NumFDs reset bufferOffset, we
* put it back to what it was, so everything works
* again next time we run this method
*/
client->rx->bufferOffset = client->rx->bufferLength;
return;
}
} }
/* Definitely finished reading, so remove from queue */ /* Definitely finished reading, so remove from queue */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册