Mir

Merge lp:~albaguirre/mir/fix-1481034 into lp:mir

Proposed by Alberto Aguirre on 2015-08-03
Status: Merged
Approved by: Alberto Aguirre on 2015-08-04
Approved revision: 2808
Merged at revision: 2808
Proposed branch: lp:~albaguirre/mir/fix-1481034
Merge into: lp:mir
Diff against target: 44 lines (+9/-9)
1 file modified
src/server/input/default_input_manager.cpp (+9/-9)
To merge this branch: bzr merge lp:~albaguirre/mir/fix-1481034
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve on 2015-08-04
Alan Griffiths 2015-08-03 Approve on 2015-08-04
Review via email: mp+266781@code.launchpad.net

Commit Message

input: Avoid throwing exception while unwinding input thread

The input thread exception handler and the the enqueued action can race to set a std::promise during start.
Have the promise be owned and set by the starting action only instead.

Description of the Change

input: Avoid throwing exception while unwinding input thread

The input thread exception handler and the the enqueued action can race to set a std::promise during start.
Have the promise be owned and set by the starting action only instead.

To post a comment you must log in.
Chris Halse Rogers (raof) wrote :

Hah! I happen to have also run into and fixed this in the glib-mainloop-deadlock branch.

I think http://bazaar.launchpad.net/~raof/mir/fix-deadlock-in-glib-alarm/revision/2802 is a cleaner fix. There's no reason for the exception handler sent to ThreadedDispatcher to touch the started_promise at all, as ~promise() sets the exception iff a value hasn't been set and we're already going to mir::terminate_with_current_exception().

Alberto Aguirre (albaguirre) wrote :

@Chris, yeah I'll cherry pick your fix in here. Thanks!

lp:~albaguirre/mir/fix-1481034 updated on 2015-08-04
2807. By Chris Halse Rogers on 2015-08-04

Use Chris' fix instead

Alan Griffiths (alan-griffiths) wrote :

24 +
25 + /* Emulate move-semantics for started_promise.
26 + *
27 + * We need the starting-lambda to own started_promise so that it is guaranteed that
28 + * started_future gets signalled; either by ->set_value in the success path or
29 + * by the destruction of started_promise generating a broken_promise exception.
30 + */
31 + started_promise.reset();

Couldn't we just do a move capture in the lambda expression?

   queue->enqueue([this, promise = std::move(started_promise)]()

review: Needs Information
lp:~albaguirre/mir/fix-1481034 updated on 2015-08-04
2808. By Alberto Aguirre on 2015-08-04

Use move capture instead

Alberto Aguirre (albaguirre) wrote :

> Couldn't we just do a move capture in the lambda expression?
>
> queue->enqueue([this, promise = std::move(started_promise)]()

Yep.

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/server/input/default_input_manager.cpp'
2--- src/server/input/default_input_manager.cpp 2015-07-31 08:20:19 +0000
3+++ src/server/input/default_input_manager.cpp 2015-08-04 16:56:59 +0000
4@@ -86,32 +86,32 @@
5
6 legacy_dispatchable->start();
7
8- auto const started_promise = std::make_shared<std::promise<void>>();
9- auto const weak_started_promise = std::weak_ptr<std::promise<void>>(started_promise);
10+ auto started_promise = std::make_shared<std::promise<void>>();
11 auto started_future = started_promise->get_future();
12
13- queue->enqueue([this,weak_started_promise]()
14+ /*
15+ * We need the starting-lambda to own started_promise so that it is guaranteed that
16+ * started_future gets signalled; either by ->set_value in the success path or
17+ * by the destruction of started_promise generating a broken_promise exception.
18+ */
19+ queue->enqueue([this,promise = std::move(started_promise)]()
20 {
21 start_platforms();
22 // TODO: Udev monitoring is still not separated yet - an initial scan is necessary to open
23 // devices, this will be triggered through the first call to dispatch->InputReader->loopOnce.
24 legacy_dispatchable->dispatch(dispatch::FdEvent::readable);
25- auto const started_promise =
26- std::shared_ptr<std::promise<void>>(weak_started_promise);
27- started_promise->set_value();
28+ promise->set_value();
29 });
30
31 input_thread = std::make_unique<dispatch::ThreadedDispatcher>(
32 "Mir/Input Reader",
33 multiplexer,
34- [this,weak_started_promise]()
35+ [this]()
36 {
37 stop_platforms();
38 multiplexer->remove_watch(queue);
39 multiplexer->remove_watch(legacy_dispatchable);
40 state = State::stopped;
41- if (auto started_promise = weak_started_promise.lock())
42- started_promise->set_exception(std::current_exception());
43 mir::terminate_with_current_exception();
44 });
45

Subscribers

People subscribed via source and target branches