[libvirt] [PATCH] fix bug libvirt daemon deadlock when another force console break down an existed console client when this deadlock hanppened, libvirtd backtrace as follow, a typical ABBA deadlock circumstance:
Michal Privoznik
mprivozn at redhat.com
Fri Nov 22 09:41:37 UTC 2019
On 11/22/19 8:00 AM, Lance Liu wrote:
> Thank you!
> But it looks like libvirtd daemon stream module still has bug lead to
> process segfault if applied this patch(if not, it will lead libvirtd
> deadlock).I have got the cause, but it seems difficult to fix it with
> present codes。
> Bug reproduce:
> 1. add sleep(3) in daemonStreamFilter() so it is easily to get the
> point, as follows
> static int
> daemonStreamFilter(virNetServerClientPtr client,
> virNetMessagePtr msg,
> void *opaque)
> {
> daemonClientStream *stream = opaque;
> int ret = 0;
> static int first = 1;
>
> // if (first) {
> // notify_force_console();
> // VIR_ERROR("notify force console to break this client
> down!client: %p", client);
> // sleep(30);
> // VIR_ERROR("sleep 10 finished");
> // }
> VIR_ERROR("stream: %p, filter_id: %d", stream, stream->filterID);
> virObjectUnlock(client);
> sleep(3);
> virMutexLock(&stream->priv->lock);
> virObjectLock(client);
> 2. build the libvirtd with new code, then replace the libvirtd
> 3. use virsh console to open a vm's console tty, then just input many
> chars in the console
> 4. open new terminal, then use virsh console --force to break the
> previous client, then you'll got libvirtd segfault
>
> it looks because when daemonStreamEvent() with para events
> as VIR_STREAM_EVENT_ERROR is called, it will remove stream and free stream,
> but daemonStreamFilter still waiting stream->priv->lock mutex, thus
> cause invalid memory access
Yes, this is exactly what is happening.
>
> To fix this, I think the most effective and clean way is to drop
> client->priv->lock elements, just use client object lock。But for
> current code, it's not easy to do that。
> also, a workaroud scheme is to add a big lock, but is ugly and low
> efficient。
>
> Any good ideas?
I think we need to get back to drawing board. In the original problem
you observed ABBA, but also was patching older libvirt. I convinced
myself that the problem still occurs even with (at that point) current
master:
1) virNetServerClientDispatchEvent() locks @client,
virNetServerClientDispatchRead()
daemonStreamFilter() which locks stream->priv->lock;
on the other hand:
2) daemonStreamEvent() locks stream->priv->lock,
virNetServerClientClose() which locks @client; /* there are other
functions called over @client which also lock @client, I've just picked
one */
So there is ABBA pattern. However, there might be another lock that is
breaking the pattern (although I don't see it now): CAB and another
thread then does CBA.
Do you have a reproducer for your original problem? Does it reproduce on
the current master (after you revert the patch I've merged of course).
Michal
More information about the libvir-list
mailing list