After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 759644 - GVolumeMonitor: Results don't reflect current state but state when application was launched
GVolumeMonitor: Results don't reflect current state but state when applicatio...
Status: RESOLVED OBSOLETE
Product: glib
Classification: Platform
Component: gio
2.52.x
Other All
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2015-12-18 17:37 UTC by Christian Stadelmann
Modified: 2018-05-24 18:25 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
A sample C file to test bug. (825 bytes, text/plain)
2015-12-18 17:37 UTC, Christian Stadelmann
Details
The sample C file fix (1.21 KB, text/plain)
2017-06-26 14:32 UTC, Ondrej Holy
Details

Description Christian Stadelmann 2015-12-18 17:37:29 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.
Comment 1 Christian Stadelmann 2017-06-25 23:09:33 UTC
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.
Comment 2 Philip Withnall 2017-06-26 09:49:28 UTC
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
Comment 3 Christian Stadelmann 2017-06-26 10:11:03 UTC
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
Comment 4 Philip Withnall 2017-06-26 10:26:59 UTC
(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.)
Comment 5 Christian Stadelmann 2017-06-26 11:21:27 UTC
(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
Comment 6 Christian Stadelmann 2017-06-26 11:31:41 UTC
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
Comment 7 Philip Withnall 2017-06-26 11:53:51 UTC
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.
Comment 8 Christian Stadelmann 2017-06-26 12:11:24 UTC
(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.
Comment 9 Christian Stadelmann 2017-06-26 13:04:49 UTC
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.
Comment 10 Ondrej Holy 2017-06-26 14:32:47 UTC
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...
Comment 11 Philip Withnall 2017-07-04 10:34:21 UTC
(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?
Comment 12 GNOME Infrastructure Team 2018-05-24 18:25:42 UTC
-- 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.