提交 ad063f61 编写于 作者: N Nikolay Shirokovskiy 提交者: Michal Privoznik

rpc: client: incapsulate error checks

Checking virNetClientStreamRaiseError without client lock
is racy which is fixed in [1] for example. Thus let's remove such checks
when we are sending message to server. And in other cases
(like virNetClientStreamRecvHole for example) let's move the check
into client stream code.

virNetClientStreamRecvPacket already have stream lock so we could
introduce another error checking function like virNetClientStreamRaiseErrorLocked
but as error is set when both client and stream lock are hold we
can remove locking from virNetClientStreamRaiseError because all
callers hold either client or stream lock.

Also let's split virNetClientStreamRaiseErrorLocked into checking
state function and checking message send status function. They are
same yet.

[1] 1b6a29c21: rpc: fix race on stream abort/finish and server side abort
Signed-off-by: NNikolay Shirokovskiy <nshirokovskiy@virtuozzo.com>
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
上级 8457fd50
...@@ -54,6 +54,8 @@ virNetClientProgramNew; ...@@ -54,6 +54,8 @@ virNetClientProgramNew;
# rpc/virnetclientstream.h # rpc/virnetclientstream.h
virNetClientStreamCheckSendStatus;
virNetClientStreamCheckState;
virNetClientStreamEOF; virNetClientStreamEOF;
virNetClientStreamEventAddCallback; virNetClientStreamEventAddCallback;
virNetClientStreamEventRemoveCallback; virNetClientStreamEventRemoveCallback;
...@@ -61,7 +63,6 @@ virNetClientStreamEventUpdateCallback; ...@@ -61,7 +63,6 @@ virNetClientStreamEventUpdateCallback;
virNetClientStreamMatches; virNetClientStreamMatches;
virNetClientStreamNew; virNetClientStreamNew;
virNetClientStreamQueuePacket; virNetClientStreamQueuePacket;
virNetClientStreamRaiseError;
virNetClientStreamRecvHole; virNetClientStreamRecvHole;
virNetClientStreamRecvPacket; virNetClientStreamRecvPacket;
virNetClientStreamSendHole; virNetClientStreamSendHole;
......
...@@ -5600,9 +5600,6 @@ remoteStreamSend(virStreamPtr st, ...@@ -5600,9 +5600,6 @@ remoteStreamSend(virStreamPtr st,
virNetClientStreamPtr privst = st->privateData; virNetClientStreamPtr privst = st->privateData;
int rv; int rv;
if (virNetClientStreamRaiseError(privst))
return -1;
remoteDriverLock(priv); remoteDriverLock(priv);
priv->localUses++; priv->localUses++;
remoteDriverUnlock(priv); remoteDriverUnlock(priv);
...@@ -5634,9 +5631,6 @@ remoteStreamRecvFlags(virStreamPtr st, ...@@ -5634,9 +5631,6 @@ remoteStreamRecvFlags(virStreamPtr st,
virCheckFlags(VIR_STREAM_RECV_STOP_AT_HOLE, -1); virCheckFlags(VIR_STREAM_RECV_STOP_AT_HOLE, -1);
if (virNetClientStreamRaiseError(privst))
return -1;
remoteDriverLock(priv); remoteDriverLock(priv);
priv->localUses++; priv->localUses++;
remoteDriverUnlock(priv); remoteDriverUnlock(priv);
...@@ -5676,9 +5670,6 @@ remoteStreamSendHole(virStreamPtr st, ...@@ -5676,9 +5670,6 @@ remoteStreamSendHole(virStreamPtr st,
virNetClientStreamPtr privst = st->privateData; virNetClientStreamPtr privst = st->privateData;
int rv; int rv;
if (virNetClientStreamRaiseError(privst))
return -1;
remoteDriverLock(priv); remoteDriverLock(priv);
priv->localUses++; priv->localUses++;
remoteDriverUnlock(priv); remoteDriverUnlock(priv);
...@@ -5709,9 +5700,6 @@ remoteStreamRecvHole(virStreamPtr st, ...@@ -5709,9 +5700,6 @@ remoteStreamRecvHole(virStreamPtr st,
virCheckFlags(0, -1); virCheckFlags(0, -1);
if (virNetClientStreamRaiseError(privst))
return -1;
remoteDriverLock(priv); remoteDriverLock(priv);
priv->localUses++; priv->localUses++;
remoteDriverUnlock(priv); remoteDriverUnlock(priv);
...@@ -5834,9 +5822,6 @@ remoteStreamCloseInt(virStreamPtr st, bool streamAbort) ...@@ -5834,9 +5822,6 @@ remoteStreamCloseInt(virStreamPtr st, bool streamAbort)
remoteDriverLock(priv); remoteDriverLock(priv);
if (virNetClientStreamRaiseError(privst))
goto cleanup;
priv->localUses++; priv->localUses++;
remoteDriverUnlock(priv); remoteDriverUnlock(priv);
...@@ -5849,7 +5834,6 @@ remoteStreamCloseInt(virStreamPtr st, bool streamAbort) ...@@ -5849,7 +5834,6 @@ remoteStreamCloseInt(virStreamPtr st, bool streamAbort)
remoteDriverLock(priv); remoteDriverLock(priv);
priv->localUses--; priv->localUses--;
cleanup:
virNetClientRemoveStream(priv->client, privst); virNetClientRemoveStream(priv->client, privst);
virObjectUnref(privst); virObjectUnref(privst);
st->privateData = NULL; st->privateData = NULL;
......
...@@ -2193,7 +2193,7 @@ int virNetClientSendStream(virNetClientPtr client, ...@@ -2193,7 +2193,7 @@ int virNetClientSendStream(virNetClientPtr client,
virObjectLock(client); virObjectLock(client);
if (virNetClientStreamRaiseError(st)) if (virNetClientStreamCheckState(st) < 0)
goto cleanup; goto cleanup;
/* Check for EOF only if we are going to wait for incoming data */ /* Check for EOF only if we are going to wait for incoming data */
...@@ -2205,7 +2205,7 @@ int virNetClientSendStream(virNetClientPtr client, ...@@ -2205,7 +2205,7 @@ int virNetClientSendStream(virNetClientPtr client,
if (virNetClientSendInternal(client, msg, expectReply, false) < 0) if (virNetClientSendInternal(client, msg, expectReply, false) < 0)
goto cleanup; goto cleanup;
if (virNetClientStreamRaiseError(st)) if (virNetClientStreamCheckSendStatus(st, msg) < 0)
goto cleanup; goto cleanup;
ret = 0; ret = 0;
......
...@@ -184,14 +184,9 @@ bool virNetClientStreamMatches(virNetClientStreamPtr st, ...@@ -184,14 +184,9 @@ bool virNetClientStreamMatches(virNetClientStreamPtr st,
} }
bool virNetClientStreamRaiseError(virNetClientStreamPtr st) static
void virNetClientStreamRaiseError(virNetClientStreamPtr st)
{ {
virObjectLock(st);
if (st->err.code == VIR_ERR_OK) {
virObjectUnlock(st);
return false;
}
virRaiseErrorFull(__FILE__, __FUNCTION__, __LINE__, virRaiseErrorFull(__FILE__, __FUNCTION__, __LINE__,
st->err.domain, st->err.domain,
st->err.code, st->err.code,
...@@ -202,8 +197,31 @@ bool virNetClientStreamRaiseError(virNetClientStreamPtr st) ...@@ -202,8 +197,31 @@ bool virNetClientStreamRaiseError(virNetClientStreamPtr st)
st->err.int1, st->err.int1,
st->err.int2, st->err.int2,
"%s", st->err.message ? st->err.message : _("Unknown error")); "%s", st->err.message ? st->err.message : _("Unknown error"));
virObjectUnlock(st); }
return true;
/* MUST be called under stream or client lock */
int virNetClientStreamCheckState(virNetClientStreamPtr st)
{
if (st->err.code != VIR_ERR_OK) {
virNetClientStreamRaiseError(st);
return -1;
}
return 0;
}
/* MUST be called under stream or client lock */
int virNetClientStreamCheckSendStatus(virNetClientStreamPtr st,
virNetMessagePtr msg ATTRIBUTE_UNUSED)
{
if (st->err.code != VIR_ERR_OK) {
virNetClientStreamRaiseError(st);
return -1;
}
return 0;
} }
...@@ -474,6 +492,9 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st, ...@@ -474,6 +492,9 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
virObjectLock(st); virObjectLock(st);
reread: reread:
if (virNetClientStreamCheckState(st) < 0)
goto cleanup;
if (!st->rx && !st->incomingEOF) { if (!st->rx && !st->incomingEOF) {
virNetMessagePtr msg; virNetMessagePtr msg;
int ret; int ret;
...@@ -646,6 +667,11 @@ virNetClientStreamRecvHole(virNetClientPtr client ATTRIBUTE_UNUSED, ...@@ -646,6 +667,11 @@ virNetClientStreamRecvHole(virNetClientPtr client ATTRIBUTE_UNUSED,
virObjectLock(st); virObjectLock(st);
if (virNetClientStreamCheckState(st) < 0) {
virObjectUnlock(st);
return -1;
}
*length = st->holeLength; *length = st->holeLength;
st->holeLength = 0; st->holeLength = 0;
......
...@@ -36,7 +36,10 @@ virNetClientStreamPtr virNetClientStreamNew(virStreamPtr stream, ...@@ -36,7 +36,10 @@ virNetClientStreamPtr virNetClientStreamNew(virStreamPtr stream,
unsigned serial, unsigned serial,
bool allowSkip); bool allowSkip);
bool virNetClientStreamRaiseError(virNetClientStreamPtr st); int virNetClientStreamCheckState(virNetClientStreamPtr st);
int virNetClientStreamCheckSendStatus(virNetClientStreamPtr st,
virNetMessagePtr msg);
int virNetClientStreamSetError(virNetClientStreamPtr st, int virNetClientStreamSetError(virNetClientStreamPtr st,
virNetMessagePtr msg); virNetMessagePtr msg);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册