Mir

Merge lp:~vanvugt/mir/fix-1401488 into lp:mir

Proposed by Daniel van Vugt on 2014-12-30
Status: Merged
Approved by: Daniel van Vugt on 2015-01-06
Approved revision: 2191
Merged at revision: 2197
Proposed branch: lp:~vanvugt/mir/fix-1401488
Merge into: lp:mir
Diff against target: 50 lines (+33/-0)
1 file modified
src/server/glib_main_loop_sources.cpp (+33/-0)
To merge this branch: bzr merge lp:~vanvugt/mir/fix-1401488
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration 2014-12-30 Approve on 2015-01-06
Robert Carr (community) Approve on 2015-01-05
Kevin DuBois (community) Abstain on 2015-01-05
Cemil Azizoglu (community) Approve on 2015-01-05
Alan Griffiths 2014-12-30 Approve on 2015-01-05
Allison Lortie 2014-12-30 Pending
Review via email: mp+245443@code.launchpad.net

Commit Message

Avoid heap corruption and general instability caused by GSource destruction from another thread while the GMainLoop is iterating.
(LP: #1401488)

To post a comment you must log in.
Alan Griffiths (alan-griffiths) wrote :

8 +#ifndef GLIB_HAS_FIXED_LP_1401488

OK, we don't actually define the macro, but shouldn't it start with "MIR_"?

Daniel van Vugt (vanvugt) wrote :

GLIB_HAS_FIXED_LP_1401488 is more a matter of documentation than a functional macro. Instead of ever defining it we would probably just delete the workaround introduced here once (if) glib gets fixed. Also, it's local to the .cpp file so doesn't need any MIR_ prefix for namespace protection.

Alan Griffiths (alan-griffiths) wrote :

The "namespace protection" would be against some other project (glib) defining GLIB_XXX. Although the chances of XXX==HAS_FIXED_LP_1401488 is clearly remote.

Daniel van Vugt (vanvugt) wrote :

The chances are incredibly remote, but also useful... If GLib did define that macro then I would take it as a strong indication that it means exactly what it sounds like. So that would be a useful definition and not a conflicting definition.

Alan Griffiths (alan-griffiths) wrote :

The change looks plausible but I don't have a reliable way to reproduce the problem it purports to fix. (I also don't like the possibility of accidentally compiling a variant version of the code, but won't block in the risk of that happening.)

review: Approve
Cemil Azizoglu (cemil-azizoglu) wrote :

I tried the test case in the bug report but my machine got frozen on the server VT either way. Are you sure this is fixing it?

It does nevertheless look like the right thing to do, so approving.

review: Approve
Kevin DuBois (kdub) wrote :

given how macro-free we've been able to keep the mir code, I'd rather have the comment explaining that we cannot use g_source_unref(gsource) like we'd like to, and only have the longer fix there.

I guess if this is a critical bug though, will abstain.

review: Abstain
Robert Carr (robertcarr) wrote :

Ok

review: Approve
Daniel van Vugt (vanvugt) wrote :

Yes I did make sure I had reliable test cases for reproducing the issue before attempting this fix. Actually one is missing from the bug. I'll add it...

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/server/glib_main_loop_sources.cpp'
2--- src/server/glib_main_loop_sources.cpp 2014-11-14 19:34:33 +0000
3+++ src/server/glib_main_loop_sources.cpp 2014-12-30 09:45:05 +0000
4@@ -51,6 +51,21 @@
5 GSource* gsource;
6 };
7
8+#ifndef GLIB_HAS_FIXED_LP_1401488
9+gboolean idle_callback(gpointer)
10+{
11+ return G_SOURCE_REMOVE; // Remove the idle source. Only needed once.
12+}
13+
14+void destroy_idler(gpointer user_data)
15+{
16+ // idle_callback is never totally guaranteed to be called. However this
17+ // function is, so we do the unref here...
18+ auto gsource = static_cast<GSource*>(user_data);
19+ g_source_unref(gsource);
20+}
21+#endif
22+
23 }
24
25 /*****************
26@@ -91,7 +106,25 @@
27 {
28 pre_destruction_hook(gsource);
29 g_source_destroy(gsource);
30+
31+#ifdef GLIB_HAS_FIXED_LP_1401488
32 g_source_unref(gsource);
33+#else
34+ /*
35+ * https://bugs.launchpad.net/mir/+bug/1401488
36+ * We would like to g_source_unref(gsource); here but it's unsafe
37+ * to do so. The reason being we could be in some arbitrary thread,
38+ * and so the main loop might be mid-iteration of the same source
39+ * making callbacks. And glib lacks protection to prevent sources
40+ * getting fully free()'d mid-callback (TODO: fix glib?). So we defer
41+ * the final unref of the source to a point in the loop when it's safe:
42+ */
43+ auto main_context = g_source_get_context(gsource);
44+ auto idler = g_idle_source_new();
45+ g_source_set_callback(idler, idle_callback, gsource, destroy_idler);
46+ g_source_attach(idler, main_context);
47+ g_source_unref(idler);
48+#endif
49 }
50 }
51

Subscribers

People subscribed via source and target branches