Skip to content

Commit 2fe02e5

Browse files
authored
WorkspaceManager: Fix crash on workspace removed (#2281)
1 parent 423cdfc commit 2fe02e5

File tree

1 file changed

+22
-12
lines changed

1 file changed

+22
-12
lines changed

src/WorkspaceManager.vala

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public class Gala.WorkspaceManager : Object {
120120
// or else things might get broke
121121
DragDropAction.cancel_all_by_id ("multitaskingview-window");
122122

123-
remove_workspace (prev_workspace);
123+
queue_remove_workspace (prev_workspace);
124124
}
125125
}
126126

@@ -178,7 +178,7 @@ public class Gala.WorkspaceManager : Object {
178178
&& Utils.get_n_windows (workspace, true, window) == 0
179179
&& workspace != last_workspace
180180
) {
181-
remove_workspace (workspace);
181+
queue_remove_workspace (workspace);
182182
}
183183

184184
// if window is the second last and empty, make it the last workspace
@@ -187,7 +187,7 @@ public class Gala.WorkspaceManager : Object {
187187
&& Utils.get_n_windows (workspace, true, window) == 0
188188
&& workspace.index () == last_workspace_index - 1
189189
) {
190-
remove_workspace (last_workspace);
190+
queue_remove_workspace (last_workspace);
191191
}
192192
}
193193

@@ -221,12 +221,27 @@ public class Gala.WorkspaceManager : Object {
221221
manager.append_new_workspace (false, display.get_current_time ());
222222
}
223223

224+
private void queue_remove_workspace (Meta.Workspace workspace) {
225+
// workspace has already been removed
226+
if (workspace in workspaces_marked_removed) {
227+
return;
228+
}
229+
230+
workspaces_marked_removed.add (workspace);
231+
232+
// We might be here because of a signal emition from the ws machinery (e.g. workspace.window_removed).
233+
// Often the function emitting the signal doesn't take a ref on the ws so if we remove it right
234+
// away it will be freed. But because the function often accesses it after the singal emition this leads
235+
// to warnings and in some cases a crash.
236+
Idle.add (() => remove_workspace (workspace));
237+
}
238+
224239
/**
225240
* Make sure we switch to a different workspace and remove the given one
226241
*
227242
* @param workspace The workspace to remove
228243
*/
229-
private void remove_workspace (Meta.Workspace workspace) {
244+
private bool remove_workspace (Meta.Workspace workspace) {
230245
unowned Meta.Display display = workspace.get_display ();
231246
unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
232247
var time = display.get_current_time ();
@@ -246,17 +261,12 @@ public class Gala.WorkspaceManager : Object {
246261
}
247262
}
248263

249-
// workspace has already been removed
250-
if (workspace in workspaces_marked_removed) {
251-
return;
252-
}
253-
254264
workspace.window_added.disconnect (queue_window_added);
255265
workspace.window_removed.disconnect (window_removed);
256266

257-
workspaces_marked_removed.add (workspace);
258-
259267
manager.remove_workspace (workspace, time);
268+
269+
return Source.REMOVE;
260270
}
261271

262272
/**
@@ -292,7 +302,7 @@ public class Gala.WorkspaceManager : Object {
292302
foreach (var workspace in manager.get_workspaces ()) {
293303
var last_index = manager.get_n_workspaces () - 1;
294304
if (Utils.get_n_windows (workspace) == 0 && workspace.index () != last_index) {
295-
remove_workspace (workspace);
305+
queue_remove_workspace (workspace);
296306
}
297307
}
298308
}

0 commit comments

Comments
 (0)