Bug#996805: nemo: Freezes when opening a folder that contains a large GIF file
Control: affects -1 + gdk-pixbuf Il 22/10/2021 05:21, Johan Croft ha scritto: Hello, I decided to take another shot at this and I still can't believe it, but I actually ended up fixing it. Hooking a debugger to Nemo and stopping it in the middle of the freeze shows that it's hanging inside libgdk_pixbuf-2.0.so. More specifically, once Nemo calls gdk_pixbuf_loader_write() inside get_pixbuf_for_content() (in nemo-directory-async.c) the function takes a very long time to return or never returns at all for very large GIFs. Most likely, this means there's a regression inside libgdk_pixbuf-2.0.so, which also makes sense in the context of my original report: the bug is present in Debian 11 and Arch (both use version 2.42), but not in Debian 10 (which uses version 2.38) nor in Mint 20.1 (which uses version 2.40). The code of get_pixbuf_for_content() between Debian and Mint's source packages is also the same, and doesn't change for Nemo 5.0.3 either, so the whole picture is congruent. I tried "forward-porting" Buster's libgdk_pixbuf just for confirmation, but unfortunately that doesn't seem compatible with the rest of the system. When looking at get_pixbuf_for_content(), there's a comment mentioning the need to call gdk_pixbuf_loader_write() with chunks of the file to process, however Nemo's implementation doesn't actually do this and shoves the whole file in one go at gdk_pixbuf_loader_write() which then seems to choke on it. Making slight adjustments so that the file is actually served in chunks as the comment mentions actually fixes the whole issue. I recompiled Nemo with such changes and the fix seems to hold. Nemo's original get_pixbuf_for_content() is pretty self-contained so it can be extracted into a standalone program of just a handful of lines as a minimal reproducible example. I did it and tried it both on Debian 11 and Mint 20.1 and the behavior is as expected: it freezes on Debian but works on Mint. I also tested the changes in this way to take time measurements for different chunk sizes and compare performance between the fixed version and the original one on Mint. I'm attaching a patch for Nemo's get_pixbuf_for_content() as well as the examples mentioned (which aren't very nice, but should be good enough to illustrate). I hope this is useful. This is my first time reporting an issue on and making a submission to an open source project, so I apologize if something doesn't turn out to be tidy enough. My only other question is whether there's any chance of seeing this properly fixed for Bullseye in some way in the future. Thanks for your contribution, I don't have time to look better to this now, I think will be better to check on gdk-pixbuf if a better fix is needed on it OpenPGP_0x680668AE907F101D.asc Description: OpenPGP public key OpenPGP_signature Description: OpenPGP digital signature
Bug#996805: nemo: Freezes when opening a folder that contains a large GIF file
Hello, I decided to take another shot at this and I still can't believe it, but I actually ended up fixing it. Hooking a debugger to Nemo and stopping it in the middle of the freeze shows that it's hanging inside libgdk_pixbuf-2.0.so. More specifically, once Nemo calls gdk_pixbuf_loader_write() inside get_pixbuf_for_content() (in nemo-directory-async.c) the function takes a very long time to return or never returns at all for very large GIFs. Most likely, this means there's a regression inside libgdk_pixbuf-2.0.so, which also makes sense in the context of my original report: the bug is present in Debian 11 and Arch (both use version 2.42), but not in Debian 10 (which uses version 2.38) nor in Mint 20.1 (which uses version 2.40). The code of get_pixbuf_for_content() between Debian and Mint's source packages is also the same, and doesn't change for Nemo 5.0.3 either, so the whole picture is congruent. I tried "forward-porting" Buster's libgdk_pixbuf just for confirmation, but unfortunately that doesn't seem compatible with the rest of the system. When looking at get_pixbuf_for_content(), there's a comment mentioning the need to call gdk_pixbuf_loader_write() with chunks of the file to process, however Nemo's implementation doesn't actually do this and shoves the whole file in one go at gdk_pixbuf_loader_write() which then seems to choke on it. Making slight adjustments so that the file is actually served in chunks as the comment mentions actually fixes the whole issue. I recompiled Nemo with such changes and the fix seems to hold. Nemo's original get_pixbuf_for_content() is pretty self-contained so it can be extracted into a standalone program of just a handful of lines as a minimal reproducible example. I did it and tried it both on Debian 11 and Mint 20.1 and the behavior is as expected: it freezes on Debian but works on Mint. I also tested the changes in this way to take time measurements for different chunk sizes and compare performance between the fixed version and the original one on Mint. I'm attaching a patch for Nemo's get_pixbuf_for_content() as well as the examples mentioned (which aren't very nice, but should be good enough to illustrate). I hope this is useful. This is my first time reporting an issue on and making a submission to an open source project, so I apologize if something doesn't turn out to be tidy enough. My only other question is whether there's any chance of seeing this properly fixed for Bullseye in some way in the future.--- ../original/nemo-4.8.6/libnemo-private/nemo-directory-async.c 2021-03-05 08:57:48.0 -0500 +++ libnemo-private/nemo-directory-async.c 2021-10-21 22:27:11.0 -0400 @@ -3902,7 +3902,7 @@ gboolean res; GdkPixbuf *pixbuf, *pixbuf2; GdkPixbufLoader *loader; - gsize chunk_len; + gsize chunk_len = 1; pixbuf = NULL; loader = gdk_pixbuf_loader_new (); @@ -3912,12 +3912,20 @@ /* For some reason we have to write in chunks, or gdk-pixbuf fails */ res = TRUE; - while (res && file_len > 0) { + while (res && file_len > chunk_len) { + res = gdk_pixbuf_loader_write (loader, (guchar *) file_contents, chunk_len, NULL); + file_contents += chunk_len; + file_len -= chunk_len; + } + + if (res && file_len != 0) + { chunk_len = file_len; res = gdk_pixbuf_loader_write (loader, (guchar *) file_contents, chunk_len, NULL); file_contents += chunk_len; file_len -= chunk_len; } + if (res) { res = gdk_pixbuf_loader_close (loader, NULL); } //needs libgdk-pixbuf2.0-dev installed. //Compile with g++ mre_original.cpp -L/usr/lib/x86_64-linux-gnu/ -lgdk_pixbuf-2.0 -lglib-2.0 -lgobject-2.0 -I/usr/include/gdk-pixbuf-2.0/gdk-pixbuf/ -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/glib-2.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -o original #include #include #include "gdk-pixbuf.h" #include using namespace std; static GdkPixbuf * get_pixbuf_for_content (int file_len, char *file_contents); int main(int argc, char *argv[]) { if(argc != 2) { printf("wrong number of arguments\n"); exit(123); } char *filePath=argv[1]; FILE *fp = fopen(filePath, "rb"); if(fp==nullptr) { printf("error openning file\n"); exit(123); } fseek(fp, 0, SEEK_END); int size = ftell(fp); fseek(fp, 0, SEEK_SET); std::vector fileContents; fileContents.resize(size); char * ptr = fileContents.data(); int readQty = fread(ptr, 1, size, fp); fclose(fp); if(readQty != size) { printf("error reading file: read: %d, size: %d\n", readQty, size); exit(123); } get_pixbuf_for_content(size, ptr); return 0; } static GdkPixbuf * get_pixbuf_for_content (int file_len, char *file_contents) { gboolean res; GdkPixbuf *pixbuf, *pixbuf2; GdkPixbufLoader *loader; gsize chunk_len; pixbuf = NULL; loader = gdk_pixbuf_loader_new (); /* For some reason we have to write in chunks, or gdk-pixbuf fails */ res = TRUE; while (res && file_len > 0) { chunk_len = file_len; res =
Bug#996805: nemo: Freezes when opening a folder that contains a large GIF file
Package: nemo Version: 4.8.6-2 Severity: normal X-Debbugs-Cc: jcdeb...@protonmail.ch Dear Maintainer, * What led up to the situation? After Upgrading to Debian 11, opening a folder that contained a big GIF file caused all open Nemo windows to freeze. Opening a single folder with a 10MB GIF causes every opened Nemo window to freeze for about 20 seconds and to use 100% of a processor core on a Ryzen 5900X system. This only happens when using Icon view for the folder in question and only when using the maximum zoom available. It does not happen in List view nor in Compact view nor at smaller zoom levels. It did not happen on Debian 10. The bigger the GIF file the more Nemo takes to unfreeze. I have a directory with a few much bigger GIF files in it and I cannot visit it on my system, while other folders with smaller GIFs take many seconds to load. * What exactly did you do (or not do) that was effective (or ineffective)? I tried a clean installation of Debian 11 on a virtual machine to rule out configuration issues with my system, and I was able to reproduce the issue on the VM as well. I also upgraded the VM to testing (which has Nemo 5.0.3), and it seems it is also affected by the issue. I looked for a solution online and found a Linux Mint bugtracker issue regarding slowdowns when icon captions are enabled, but disabling them did not change anything. It is worth noting however that it is coincidentally at the maximum zoom level that more captions show. There is additionally an issue on their bugtracker describing the same problem I am reporting, reported by an Arch user (see https://github.com/linuxmint/nemo/issues/2756), however it seems the Mint team was unable to reproduce it. I proceeded to make a VM with Linux Mint 20.1 and I could not reproduce the issue either despite the fact that Mint 20.1 ships with the same Nemo version as Debian 11 (Nemo 4.8.6), so it seems this might be an issue with other distributions. Disabling thumbnails effectively makes the issue disappear. Nemo uses gdk-pixbuf-thumbnailer to generate thumbnails for GIF files, but running the same command Nemo uses to create a thumbnail for a big GIF on the command line exits immediately with success. I attempted to configure ffmpegthumbnailer to be used for GIF files thumbnail generation and it didn't seem to have any effect on Nemo freezing either. Running nemo --debug on a folder with a large GIF file does not seem to provide any hints. Running strace on nemo in the same conditions shows nemo hangs in a loop calling mmap/mremap, however that's not very helpful. I'm out of ideas on how to debug further. Considering the ease of reproduction and that the logs don't seem to point to anything evident, I'm not including them in this report, but I can include them later on if necessary. * What was the outcome of this action? Nothing really worked. The only solution is to dodge the issue by disabling thumbnails or using other view styles or zoom levels. * What outcome did you expect instead? The folder with the large GIF file to open in a reasonable amount of time with no system effort. Test GIFs of different sizes can be generated with ease from any video with ffmpeg (e.g. ffmpeg -t 5 -i output.gif). Every one I tried caused the same issue. -- System Information: Debian Release: 11.1 APT prefers stable-updates APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'stable') Architecture: amd64 (x86_64) Kernel: Linux 5.10.0-9-amd64 (SMP w/2 CPU threads) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE not set Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages nemo depends on: ii cinnamon-desktop-data 4.8.1-2 ii desktop-file-utils 0.26-1 ii gsettings-desktop-schemas 3.38.0-2 ii gvfs 1.46.2-1 ii libatk1.0-02.36.0-2 ii libc6 2.31-13+deb11u2 ii libcairo-gobject2 1.16.0-5 ii libcairo2 1.16.0-5 ii libcinnamon-desktop4 4.8.1-2 ii libexempi8 2.5.2-1 ii libexif12 0.6.22-3 ii libgail-3-03.24.24-4 ii libgdk-pixbuf-2.0-02.42.2+dfsg-1 ii libglib2.0-0 2.66.8-1 ii libglib2.0-data2.66.8-1 ii libgtk-3-0 3.24.24-4 ii libnemo-extension1 4.8.6-2 ii libnotify4 0.7.9-3 ii libpango-1.0-0 1.46.2-3 ii libpangocairo-1.0-01.46.2-3 ii libselinux13.1-3 ii libx11-6 2:1.7.2-1 ii libxapp1 2.0.7-1 ii libxml22.9.10+dfsg-6.7 ii nemo-data 4.8.6-2 ii shared-mime-info 2.0-1 Versions of packages nemo recommends: ii cinnamon-l10n4.8.3-1 ii gvfs-backends