I'm looking into this with the help claude-code. This may be caused by a
race condition in locations.js, and I am testing the following changes.
I will update this bug if it fixes the issue.
## Analysis
The ubuntu-dock extension's `locations.js` accesses a GProxyVolume
object after the CD has been ejected and gvfs has disposed of the
volume. This use-after-free corrupts heap memory, causing an immediate
crash (signal 6 / SIGABRT from glibc's malloc corruption detection).
### Stack trace breakdown
**Line 504** (`MountableVolumeAppInfo.vfunc_get_id`):
```javascript
vfunc_get_id() {
const uuid = this.mount?.get_uuid() ?? this.volume.get_uuid();
// ^^^^^^^^^^^^^^^^^^^
// Accesses disposed GProxyVolume here - no null/disposed check
return uuid ? 'mountable-volume:%s'.format(uuid) : super.vfunc_get_id();
}
```
**Line 316** (`_updateLocationIcon` catch block):
```javascript
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e, 'Impossible to update icon for %s'.format(this.get_id()));
// ^^^^^^^^^^^
// This calls vfunc_get_id() which accesses the disposed volume
}
```
### Root cause: Race condition on volume removal
The `Removables` class (line 1383-1503) monitors `Gio.VolumeMonitor` for
volume events. When a CD is ejected:
1. **gvfs disposes** the `GProxyVolume` object immediately
2. **Signal handlers still fire** - the `changed` signal handler at line 574
may trigger `_update()`
3. **`volume-removed` arrives later** - cleanup in `_onVolumeRemoved()` (line
1472) hasn't run yet
4. **Async operations in flight** - `_updateLocationIcon()` is async and may
still be running
### Specific problems in the code
1. **No disposed check** - `vfunc_get_id()` at line 504 accesses
`this.volume.get_uuid()` without checking if volume is still valid
2. **Signal handler race** - `_monitorChanges()` (line 570) connects to
`removable.changed`, but doesn't disconnect when the volume is about to
be disposed
3. **Async operation not cancelled early enough** - The cancellable is
only set to null *after* finding the volume in `_onVolumeRemoved()`, but
async operations may already be in the error path
### Proposed fixes
```javascript
// Fix 1: Guard vfunc_get_id (line 504)
vfunc_get_id() {
try {
const uuid = this.mount?.get_uuid() ?? this.volume?.get_uuid?.();
return uuid ? 'mountable-volume:%s'.format(uuid) : super.vfunc_get_id();
} catch (e) {
return super.vfunc_get_id();
}
}
// Fix 2: Cancel operations BEFORE accessing disposed objects
// In _onVolumeRemoved (line 1472), cancel first:
_onVolumeRemoved(volume) {
const volumeIndex = this._volumeApps.findIndex(({appInfo}) =>
appInfo.volume === volume);
if (volumeIndex !== -1) {
const [volumeApp] = this._volumeApps.splice(volumeIndex, 1);
volumeApp.appInfo.cancellable?.cancel(); // Cancel FIRST
volumeApp.destroy();
this.emit('changed');
}
}
```
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2137078
Title:
GNOME Shell crashes after CD eject - ubuntu-dock accesses disposed
GProxyVolume
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/gnome-shell-extension-ubuntu-dock/+bug/2137078/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs