Mir

Merge lp:~raof/mir/remove-eventloop-self-immolation into lp:mir

Proposed by Chris Halse Rogers
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 2474
Proposed branch: lp:~raof/mir/remove-eventloop-self-immolation
Merge into: lp:mir
Diff against target: 96 lines (+29/-28)
2 files modified
src/common/dispatch/simple_dispatch_thread.cpp (+8/-2)
tests/unit-tests/dispatch/test_simple_dispatch_thread.cpp (+21/-26)
To merge this branch: bzr merge lp:~raof/mir/remove-eventloop-self-immolation
Reviewer Review Type Date Requested Status
Alan Griffiths Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+255767@code.launchpad.net

Commit message

Abort with an error message if attempting to destroy SimpleDispatchThread from a dispatch() callback.

This replaces the previous behaviour of detaching the thread and continuing, which caused problems in the tests.
Fixes: https://bugs.launchpad.net/mir/+bug/1441620

Description of the change

Abort with an error message if attempting to destroy SimpleDispatchThread from a dispatch() callback.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/common/dispatch/simple_dispatch_thread.cpp'
2--- src/common/dispatch/simple_dispatch_thread.cpp 2015-04-08 03:02:37 +0000
3+++ src/common/dispatch/simple_dispatch_thread.cpp 2015-04-10 01:53:32 +0000
4@@ -18,6 +18,7 @@
5
6 #include "mir/dispatch/simple_dispatch_thread.h"
7 #include "mir/dispatch/dispatchable.h"
8+#include "mir/logging/logger.h"
9 #include "utils.h"
10
11 #include <sys/epoll.h>
12@@ -136,8 +137,13 @@
13 if (eventloop.get_id() == std::this_thread::get_id())
14 {
15 // We're being destroyed from within the dispatch callback
16- // That's OK; we'll exit once we return back to wait_for_events_forever
17- eventloop.detach();
18+ // Attempting to join the eventloop will result in a trivial deadlock.
19+ //
20+ // The std::thread destructor will call std::terminate() for us, let's
21+ // leave a useful message.
22+ mir::logging::log(mir::logging::Severity::critical,
23+ "Destroying SimpleDispatchThread from within a dispatch callback. This is a programming error.",
24+ "Dispatch");
25 }
26 else if (eventloop.joinable())
27 {
28
29=== modified file 'tests/unit-tests/dispatch/test_simple_dispatch_thread.cpp'
30--- tests/unit-tests/dispatch/test_simple_dispatch_thread.cpp 2015-04-08 03:02:37 +0000
31+++ tests/unit-tests/dispatch/test_simple_dispatch_thread.cpp 2015-04-10 01:53:32 +0000
32@@ -28,6 +28,7 @@
33 #include <fcntl.h>
34
35 #include <atomic>
36+#include <thread>
37
38 #include <gtest/gtest.h>
39 #include <gmock/gmock.h>
40@@ -192,32 +193,6 @@
41 EXPECT_FALSE(dispatched_closed->wait_for(std::chrono::seconds{1}));
42 }
43
44-TEST_F(SimpleDispatchThreadTest, handles_destruction_from_dispatch_callback)
45-{
46- using namespace testing;
47- using namespace std::chrono_literals;
48-
49- auto dispatched = std::make_shared<mt::Signal>();
50- auto assignment_made = std::make_shared<mt::Signal>();
51- md::SimpleDispatchThread* dispatcher{nullptr};
52-
53- auto dispatchable = std::make_shared<mt::TestDispatchable>([dispatched, &dispatcher, assignment_made]()
54- {
55- assignment_made->wait_for(10s);
56- delete dispatcher;
57- dispatched->raise();
58- });
59-
60- dispatchable->trigger();
61- dispatchable->trigger();
62-
63- dispatcher = new md::SimpleDispatchThread{dispatchable};
64-
65- assignment_made->raise();
66-
67- EXPECT_TRUE(dispatched->wait_for(10s));
68-}
69-
70 // Regression test for: lp #1439719
71 // The bug involves uninitialized memory and is also sensitive to signal
72 // timings, so this test does not always catch the problem. However, repeated
73@@ -263,3 +238,23 @@
74 auto const result = child->wait_for_termination(10s);
75 EXPECT_TRUE(result.succeeded());
76 }
77+
78+using SimpleDispatchThreadDeathTest = SimpleDispatchThreadTest;
79+
80+TEST_F(SimpleDispatchThreadDeathTest, destroying_dispatcher_from_a_callback_is_an_error)
81+{
82+ using namespace testing;
83+ using namespace std::literals::chrono_literals;
84+
85+ EXPECT_EXIT(
86+ {
87+ md::SimpleDispatchThread* dispatcher;
88+
89+ auto dispatchable = std::make_shared<mt::TestDispatchable>([&dispatcher]() { delete dispatcher; });
90+
91+ dispatchable->trigger();
92+ dispatcher = new md::SimpleDispatchThread{dispatchable};
93+ std::this_thread::sleep_for(10s);
94+ }, KilledBySignal(SIGABRT), ".*Destroying SimpleDispatchThread.*");
95+}
96+

Subscribers

People subscribed via source and target branches