GNOME Bugzilla – Bug 759644
GVolumeMonitor: Results don't reflect current state but state when application was launched
Last modified: 2018-05-24 18:25:42 UTC
Created attachment 317639 [details] A sample C file to test bug. Steps to reproduce: 1. open python, $ python3 2. run `from gi.repository import Gio` 3. run `[m.get_name() for m in Gio.VolumeMonitor.get().get_mounts()]`. This will give you a list of all mounted partitions. 4. mount or unmount a partition. Make sure that it shows up e.g. in nautilus. 5. run command `[m.get_name() for m in Gio.VolumeMonitor.get().get_mounts()]` again. What happens: List of mounts has not changed What should happen: List of mounts should always reflect the current state, not the state when it was initialized first. Additional info: This issue is not specific to python. It can be easily reproduced with attached code. This issue seems to affect get_volumes() and get_connected_drives() too.
Actually, when using the signals on Gio.VolumeMonitor, you still get notified of these missing devices. When adding a signal handler at 5., it will receive events from volumes which were long gone.
Which GVolumeMonitor implementation gets used on your system? python3 from gi.repository import Gio m = Gio.VolumeMonitor.get() m If it’s a GUnionVolumeMonitor, could you then connect to the python3 process using gdb, and run: print g_volume_monitor_get() print (GUnionVolumeMonitor *) $1 print *$2 print $2->monitors->data print $2->monitors->next->data print $2->monitors->next->next->data # etc. until you reach the end of the linked list
Thanks for your response. I'm running Fedora 26 with glib2-2.52.3 by the way, dunno if that matters. (In reply to Philip Withnall from comment #2) > Which GVolumeMonitor implementation gets used on your system? > > python3 > from gi.repository import Gio > m = Gio.VolumeMonitor.get() > m <__gi__.GUnionVolumeMonitor object at 0x7f8ab2925438 (GUnionVolumeMonitor at 0x56466866c6c0)> > If it’s a GUnionVolumeMonitor, could you then connect to the python3 process > using gdb, and run: > > print g_volume_monitor_get() > print (GUnionVolumeMonitor *) $1 > print *$2 > print $2->monitors->data > print $2->monitors->next->data > print $2->monitors->next->next->data > # etc. until you reach the end of the linked list (gdb) attach 7567 Attaching to program: /usr/bin/python3, process 7567 [New LWP 7603] [New LWP 7604] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". 0x00007f8ac070ece3 in select () at ../sysdeps/unix/syscall-template.S:84 84 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) Missing separate debuginfos, use: dnf debuginfo-install python3-systemd-234-1.fc26.x86_64 (gdb) print g_volume_monitor_get() $1 = 0x56466866c6c0 [GUnionVolumeMonitor] (gdb) print (GUnionVolumeMonitor *) $1 $2 = 0x56466866c6c0 [GUnionVolumeMonitor] (gdb) print *$2 $3 = {parent = {parent_instance = {g_type_instance = {g_class = 0x564668500d50}, ref_count = 2, qdata = 0x564668685e70}, priv = 0x0}, monitors = 0x5646687180a0 = {0x5646686f28a0, 0x5646686f1c50, 0x5646686f2280, 0x5646686f2050, 0x5646687170c0, 0x5646686f2770}} (gdb) print $2->monitors->data $4 = (gpointer) 0x5646686f28a0 (gdb) print $2->monitors->next->data $5 = (gpointer) 0x5646686f1c50 (gdb) print $2->monitors->next->next->data $6 = (gpointer) 0x5646686f2280 (gdb) print $2->monitors->next->next->next->data $7 = (gpointer) 0x5646686f2050 (gdb) print $2->monitors->next->next->next->next->data $8 = (gpointer) 0x5646687170c0 (gdb) print $2->monitors->next->next->next->next->next->data $9 = (gpointer) 0x5646686f2770 (gdb) print $2->monitors->next->next->next->next->next->next-> A syntax error in expression, near `'. (gdb) print $2->monitors->next->next->next->next->next->next->data Cannot access memory at address 0x0
(In reply to Christian Stadelmann from comment #3) > (gdb) print $2->monitors->data > $4 = (gpointer) 0x5646686f28a0 > (gdb) print $2->monitors->next->data > $5 = (gpointer) 0x5646686f1c50 > (gdb) print $2->monitors->next->next->data > $6 = (gpointer) 0x5646686f2280 > (gdb) print $2->monitors->next->next->next->data > $7 = (gpointer) 0x5646686f2050 > (gdb) print $2->monitors->next->next->next->next->data > $8 = (gpointer) 0x5646687170c0 > (gdb) print $2->monitors->next->next->next->next->next->data > $9 = (gpointer) 0x5646686f2770 > (gdb) print $2->monitors->next->next->next->next->next->next-> > A syntax error in expression, near `'. > (gdb) print $2->monitors->next->next->next->next->next->next->data > Cannot access memory at address 0x0 Gah, I was assuming the Python gdb plugin for GLib would add the type names to these. Would you mind repeating this, but calling the following on each monitor ->data instance? g_type_name(((GTypeInstance *) blah->blah->data)->g_class->g_type) that should print the GObject class name for each. (Unfortunately, I don’t know a simpler way to do that.)
(In reply to Philip Withnall from comment #2) > Which GVolumeMonitor implementation gets used on your system? > > python3 > from gi.repository import Gio > m = Gio.VolumeMonitor.get() > m <__gi__.GUnionVolumeMonitor object at 0x7fd1e05ef630 (GUnionVolumeMonitor at 0x5609a78534c0)> > > If it’s a GUnionVolumeMonitor, could you then connect to the python3 process > using gdb, and run: > > print g_volume_monitor_get() > print (GUnionVolumeMonitor *) $1 > print *$2 > print $2->monitors->data > print $2->monitors->next->data > print $2->monitors->next->next->data > # etc. until you reach the end of the linked list (gdb) print g_volume_monitor_get() $1 = 0x5609a78534c0 [GUnionVolumeMonitor] (gdb) print (GUnionVolumeMonitor *) $1 $2 = 0x5609a78534c0 [GUnionVolumeMonitor] (gdb) print *$2 $3 = {parent = {parent_instance = {g_type_instance = {g_class = 0x5609a78cac10}, ref_count = 2, qdata = 0x5609a7912cf0}, priv = 0x0}, monitors = 0x7fd1d0001300 = {0x5609a78cd8a0, 0x5609a78ccc50, 0x5609a78cd720, 0x5609a78cd6d0, 0x5609a78f3830, 0x5609a78cd770}} (In reply to Philip Withnall from comment #4) > […] > g_type_name(((GTypeInstance *) blah->blah->data)->g_class->g_type) > […] (gdb) print $2->monitors->data $6 = (gpointer) 0x5609a78cd8a0 (gdb) call g_type_name(((GTypeInstance *) $2->monitors->data)->g_class->g_type) $7 = (const gchar *) 0x5609a781b0dd "GProxyVolumeMonitorAfc" (gdb) print $2->monitors->next->data $8 = (gpointer) 0x5609a78ccc50 (gdb) call g_type_name(((GTypeInstance *) $2->monitors->next->data)->g_class->g_type) $9 = (const gchar *) 0x5609a781b0f4 "GProxyVolumeMonitorGoa" (gdb) print $2->monitors->next->next->data $10 = (gpointer) 0x5609a78cd720 (gdb) call g_type_name(((GTypeInstance *) $2->monitors->next->next->data)->g_class->g_type) $11 = (const gchar *) 0x5609a781b10b "GProxyVolumeMonitorGPhoto2" (gdb) print $2->monitors->next->next->next->data $12 = (gpointer) 0x5609a78cd6d0 (gdb) call g_type_name(((GTypeInstance *) $2->monitors->next->next->next->data)->g_class->g_type) $13 = (const gchar *) 0x5609a781b126 "GProxyVolumeMonitorMTP" (gdb) print $2->monitors->next->next->next->next->data $14 = (gpointer) 0x5609a78f3830 (gdb) call g_type_name(((GTypeInstance *) $2->monitors->next->next->next->next->data)->g_class->g_type) $15 = (const gchar *) 0x5609a781b401 "GDaemonVolumeMonitor" (gdb) print $2->monitors->next->next->next->next->next->data $16 = (gpointer) 0x5609a78cd770 (gdb) call g_type_name(((GTypeInstance *) $2->monitors->next->next->next->next->next->data)->g_class->g_type) $17 = (const gchar *) 0x5609a781b0c2 "GProxyVolumeMonitorUDisks2" (gdb) print $2->monitors->next->next->next->next->next->next->data Cannot access memory at address 0x0
See also: $ ps -U christian -af | grep gvfs christi+ 2742 2645 0 08:31 ? 00:00:00 /usr/libexec/gvfsd christi+ 2751 2645 0 08:31 ? 00:00:00 /usr/libexec/gvfsd-fuse /run/user/1000/gvfs -f -o big_writes christi+ 2834 2645 0 08:31 ? 00:00:01 /usr/libexec/gvfs-udisks2-volume-monitor christi+ 2858 2645 0 08:31 ? 00:00:00 /usr/libexec/gvfs-mtp-volume-monitor christi+ 2862 2645 0 08:31 ? 00:00:00 /usr/libexec/gvfs-gphoto2-volume-monitor christi+ 2869 2645 0 08:31 ? 00:00:00 /usr/libexec/gvfs-goa-volume-monitor christi+ 2873 2645 0 08:31 ? 00:00:00 /usr/libexec/gvfs-afc-volume-monitor christi+ 3320 2645 0 08:31 ? 00:00:09 /usr/libexec/gvfsd-metadata christi+ 4532 2645 0 08:33 ? 00:00:00 /usr/libexec/gvfsd-http --spawner :1.12 /org/gtk/gvfs/exec_spaw/1 christi+ 9308 2645 0 09:08 ? 00:00:00 /usr/libexec/gvfsd-trash --spawner :1.12 /org/gtk/gvfs/exec_spaw/2 christi+ 9658 2645 0 09:08 ? 00:00:00 /usr/libexec/gvfsd-network --spawner :1.12 /org/gtk/gvfs/exec_spaw/5 christi+ 9809 2645 0 09:08 ? 00:00:00 /usr/libexec/gvfsd-dnssd --spawner :1.12 /org/gtk/gvfs/exec_spaw/19 christi+ 24122 2645 0 10:24 ? 00:00:00 /usr/libexec/gvfsd-admin --spawner :1.12 /org/gtk/gvfs/exec_spaw/25 --address unix:path=/run/user/1000/bus christi+ 26048 2645 0 10:36 ? 00:00:01 /usr/libexec/gvfsd-recent --spawner :1.12 /org/gtk/gvfs/exec_spaw/26 christi+ 30318 29402 0 13:30 pts/7 00:00:00 grep --color=auto gvfs
Thanks. Are you using systemd, or some other init system? Does the situation in https://bugzilla.gnome.org/show_bug.cgi?id=779607#c2 apply to your machine? Ondrej, do you have any ideas about this one? I don’t have much time to dig into the volume monitor code at the moment.
(In reply to Philip Withnall from comment #7) > Thanks. Are you using systemd, or some other init system? Systemd. > Does the situation in https://bugzilla.gnome.org/show_bug.cgi?id=779607#c2 apply to your machine? $ ls -al /etc/mtab lrwxrwxrwx. 1 root root 19 1. Nov 2015 /etc/mtab -> ../proc/self/mounts Looks like systemd is behaving as described in the other bug report, not triggering that one. Running the test case from there also immediately shows the newly mounted mount point if I attach an USB thumb drive. It also immediately shows all mount points correctly if I detach the USB thumb drive. Looks like the other bug report is about a separate issue.
Having a look at d-feet (nice DBus debugger by the way), the org.gtk.vfs.UDisks2VolumeMonitor provides a org.gtk.Private.RemoteVolumeMonitor.List() method which does get updated with correct data.
Created attachment 354509 [details] The sample C file fix The reason is pretty simple, the GVolumeMonitor infrastructure relies on signals which require running GMainLoop, but it is not running in your case. GProxyVolumeMonitor has a cache, which is not updated without the main loop and thus it still returns the initial list of mounts... See updated attachment with a functional code. But I am not sure whether it is a bug or a feature...
(In reply to Ondrej Holy from comment #10) > But I am not sure whether it is a bug or a feature... I’d say it’s neither; if you’re receiving signals from a remote process (a GVFS daemon), you need to block on receiving those signals somehow. The way GLib code blocks on receiving those signals is to have a main loop running. I guess you could expect that calling get_mounts() would pull any pending signals off D-Bus and process them, but if it doesn’t currently do that, I think that’s too big a change to make. Christian, does running a main loop give you the behaviour you expect?
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/glib/issues/1119.