<div dir="ltr"><div dir="ltr">Thanks for looking into this Rich and Daniel, and thanks for the profound explanation.<br>See my answers below.<br><br>`<span style="background-color:rgb(204,204,204)">'i' is not used inside the loop?  Or is this error intermittent?</span>` - 'i' can be removed, the error is intermittent.<br>This reproduces on libguestfs 1.46.2 and 1.48.6.<br><br>`<span style="background-color:rgb(204,204,204)">This is specifically a Python API problem or would it affect</span></div><span style="background-color:rgb(204,204,204)">the C API too?</span>` - I assume it's not in the C API, since this issue doesn't reproduce when using guestfish.<br><br><span style="background-color:rgb(204,204,204)">I would likely need a complete self-contained reproducer to really go<br>anywhere with this.</span>` - I can supply a container image with libguestfs 1.46.2 running the for loop. Let me know if that helps.<br><div dir="ltr"><div><font face="verdana, sans-serif"><br>Also, as a workaround, I avoided calling the event callback if null is returned by </font>Py_BuildValue (still print the error and release the thread).<br>This seems to work for our usage (we only use the event callbacks for logging), any potential issues I'm missing?</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Feb 13, 2023 at 8:14 PM Daniel P. Berrangé <<a href="mailto:berrange@redhat.com">berrange@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Mon, Feb 13, 2023 at 06:07:58PM +0000, Richard W.M. Jones wrote:<br>
> On Sun, Feb 12, 2023 at 03:31:08PM +0200, Yonatan Shtarkman wrote:<br>
> > Hey,<br>
> > When downloading a file whose path contains multi-byte utf-8, libguestfs<br>
> > sometimes crashes.<br>
> > This reproduces when using python, and not when using guestfish.<br>
> > <br>
> > Code to reproduce:<br>
> > for i in range(2000):<br>
> >     g.download ('/xxxó', '/tmp/1')<br>
> <br>
> 'i' is not used inside the loop?  Or is this error intermittent?<br>
> <br>
> > #0  raise (sig=<optimized out>) at ../sysdeps/unix/sysv/linux/raise.c:50<br>
> > #1  0x00007ffff7fac140 in <signal handler called> () at /lib/x86_64-linux-gnu/<br>
> > libpthread.so.0<br>
> > #2  0x00007ffff6f77701 in _Py_INCREF (op=<optimized out>) at /usr/include/<br>
> > python3.9/object.h:408<br>
> > #3  guestfs_int_py_event_callback_wrapper<br>
> >     (g=<optimized out>, flags=<optimized out>, array_len=0, array=0x0, buf_len=<br>
> > 47, buf=0x113b8a0 "gs=0x0\r\ncommandrvf: udevadm --debug settle -E \303by",<br>
> > event_handle=0, event=16, callback=0x7ffff2516600) at handle.c:137<br>
> > #4  guestfs_int_py_event_callback_wrapper<br>
> >     (g=<optimized out>, callback=0x7ffff2516600, event=16, event_handle=0,<br>
> > flags=<optimized out>, buf=0x113b8a0 "gs=0x0\r\ncommandrvf: udevadm --debug<br>
> > settle -E \303by", buf_len=47, array=0x0, array_len=0) at handle.c:104<br>
> > #5  0x00007ffff6e0076a in guestfs_int_call_callbacks_message (g=0xf31290, event<br>
> > =16, buf=0x113b8a0 "gs=0x0\r\ncommandrvf: udevadm --debug settle -E \303by",<br>
> > buf_len=47)<br>
> >     at events.c:117<br>
> > #6  0x00007ffff6e1702e in guestfs_int_log_message_callback<br>
> >     (g=g@entry=0xf31290, buf=0x113b8a0 "gs=0x0\r\ncommandrvf: udevadm --debug<br>
> > settle -E \303by", len=len@entry=47) at proto.c:145<br>
> > #7  0x00007ffff6dfb759 in handle_log_message (g=g@entry=0xf31290, conn=<br>
> > conn@entry=0x110e280) at conn-socket.c:395<br>
> > #8  0x00007ffff6dfbd63 in read_data (len=4, bufv=<optimized out>, connv=<br>
> > <optimized out>, g=<optimized out>) at conn-socket.c:179<br>
> > #9  read_data (g=0xf31290, connv=0x110e280, bufv=<optimized out>, len=4) at<br>
> > conn-socket.c:142<br>
> > #10 0x00007ffff6e1764a in recv_from_daemon (buf_rtn=0x7fffffffd858, size_rtn=<br>
> > 0x7fffffffd854, g=0xf31290) at proto.c:545<br>
> > #11 guestfs_int_recv_from_daemon (g=g@entry=0xf31290, size_rtn=size_rtn@entry=<br>
> > 0x7fffffffd854, buf_rtn=buf_rtn@entry=0x7fffffffd858) at proto.c:623<br>
> > #12 0x00007ffff6e17a5a in guestfs_int_recv<br>
> >     (g=g@entry=0xf31290, fn=fn@entry=0x7ffff6e3b3e8 "download", hdr=hdr@entry=<br>
> > 0x7fffffffd920, err=err@entry=0x7fffffffd8f0, xdrp=xdrp@entry=0x0, ret=<br>
> > ret@entry=0x0)<br>
> >     at proto.c:668<br>
> > <br>
> > I debugged this issue and noticed that the appliance logs from commandrvf are<br>
> > truncated, leading to parse failure (missing utf-8 additional bytes):<br>
> > <a href="https://github.com/libguestfs/libguestfs/blob/master/python/handle.c#L134" rel="noreferrer" target="_blank">https://github.com/libguestfs/libguestfs/blob/master/python/handle.c#L134</a><br>
> > UnicodeDecodeError: 'utf-8' codec can't decode byte 0x84 in position 0: invalid<br>
> > start byte<br>
> <br>
> So I thought we'd fixed this in:<br>
> <br>
> <a href="https://github.com/libguestfs/libguestfs/commit/0ee02e0117527b86a31b2a88a14994ce7f15571f" rel="noreferrer" target="_blank">https://github.com/libguestfs/libguestfs/commit/0ee02e0117527b86a31b2a88a14994ce7f15571f</a><br>
> <br>
> This is specifically a Python API problem or would it affect<br>
> the C API too?<br>
<br>
The difference with any C API is that almost nothing at the C level will<br>
be validating that the bytes are actually valid utf-8 sequences.<br>
<br>
So the truncated data is unlikely to result in a fatal error. Python is<br>
aggressively validating all bytes, and so you get a hard error from the<br>
truncated UTF-8.  Other languages may vary, but I've not seen anything<br>
that makes validation errors a failure in quite such an aggressive way<br>
as python. The problems with decode exceptions have hit soooo many apps<br>
using python over the past few years. Even worse if running in a C<br>
locale as python will reject anything with 8th bit set as being outside<br>
7-bit asciii, instead of being 8-bit clean in its stream handling.<br>
<br>
<br>
With regards,<br>
Daniel<br>
-- <br>
|: <a href="https://berrange.com" rel="noreferrer" target="_blank">https://berrange.com</a>      -o-    <a href="https://www.flickr.com/photos/dberrange" rel="noreferrer" target="_blank">https://www.flickr.com/photos/dberrange</a> :|<br>
|: <a href="https://libvirt.org" rel="noreferrer" target="_blank">https://libvirt.org</a>         -o-            <a href="https://fstop138.berrange.com" rel="noreferrer" target="_blank">https://fstop138.berrange.com</a> :|<br>
|: <a href="https://entangle-photo.org" rel="noreferrer" target="_blank">https://entangle-photo.org</a>    -o-    <a href="https://www.instagram.com/dberrange" rel="noreferrer" target="_blank">https://www.instagram.com/dberrange</a> :|<br>
<br>
</blockquote></div></div>