Merge lp:~phablet-team/media-hub/fix-1457129 into lp:media-hub

Proposed by Jim Hodapp
Status: Merged
Approved by: Ricardo Salveti
Approved revision: 142
Merged at revision: 141
Proposed branch: lp:~phablet-team/media-hub/fix-1457129
Merge into: lp:media-hub
Diff against target: 122 lines (+58/-15)
1 file modified
src/core/media/power/state_controller.cpp (+58/-15)
To merge this branch: bzr merge lp:~phablet-team/media-hub/fix-1457129
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Thomas Voß (community) code Approve
Review via email: mp+260343@code.launchpad.net

Commit message

Use try_lock() instead of a lock_guard to fail gracefully from rare deadlock situations.

Description of the change

Use try_lock() instead of a lock_guard to fail gracefully from rare deadlock situations.

To post a comment you must log in.
Revision history for this message
Thomas Voß (thomas-voss) wrote :

Please use a std::unique_lock instead of manually try-locking/unlocking the mutex. Would look like:

  std::unique_lock<std::mutex> ul{system_state_cookie_store_guard, std::try_to_lock};
  if (ul.owns_lock())
  {
    // do stuff.
  }

With that, the mutex is always unlocked, even in the case of exceptions.

review: Needs Fixing
Revision history for this message
Thomas Voß (thomas-voss) wrote :

LGTM.

review: Approve (code)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/core/media/power/state_controller.cpp'
2--- src/core/media/power/state_controller.cpp 2015-03-19 20:49:22 +0000
3+++ src/core/media/power/state_controller.cpp 2015-05-27 18:37:42 +0000
4@@ -98,6 +98,8 @@
5 // From core::ubuntu::media::power::StateController::Lock<DisplayState>
6 void request_acquire(media::power::DisplayState state) override
7 {
8+ std::cout << __PRETTY_FUNCTION__ << std::endl;
9+
10 if (state == media::power::DisplayState::off)
11 return;
12
13@@ -205,29 +207,51 @@
14 // the system to stay active.
15 void request_acquire(media::power::SystemState state) override
16 {
17+ std::cout << __PRETTY_FUNCTION__ << std::endl;
18+
19 if (state == media::power::SystemState::suspend)
20 return;
21
22- // Keep scope of this lock tight as to avoid
23- // deadlocks on PlayerImplementation destruction
24+ // Tighten the scope on the unique_lock
25 {
26- std::lock_guard<std::mutex> lg{system_state_cookie_store_guard};
27- if (system_state_cookie_store.count(state) > 0)
28+ // Using a unique_lock instead of lock_guard to avoid deadlocks and instead, gracefully fail
29+ std::unique_lock<std::mutex> ul{system_state_cookie_store_guard, std::try_to_lock};
30+ if (ul.owns_lock())
31+ {
32+ if (system_state_cookie_store.count(state) > 0)
33+ return;
34+ }
35+ else
36+ {
37+ std::cerr << "Failed to lock system_state_cookie_store_guard and check system lock state" << std::endl;
38+ // Prevent system_state_cookie_store.count(state) and the actual call to requestSysState below from
39+ // getting out of sync.
40 return;
41+ }
42 }
43
44 std::weak_ptr<SystemStateLock> wp{shared_from_this()};
45
46- object->invoke_method_asynchronously_with_callback<com::canonical::powerd::Interface::requestSysState, std::string>([wp, state](const core::dbus::Result<std::string>& result)
47+ object->invoke_method_asynchronously_with_callback<com::canonical::powerd::Interface::requestSysState, std::string>([wp, state, this](const core::dbus::Result<std::string>& result)
48 {
49- if (result.is_error()) // TODO(tvoss): We should log the error condition here.
50+ if (result.is_error())
51+ {
52+ std::cerr << result.error().print() << std::endl;
53 return;
54+ }
55
56 if (auto sp = wp.lock())
57 {
58- std::lock_guard<std::mutex> lg{sp->system_state_cookie_store_guard};
59+ // Tighten the scope on the unique_lock
60+ {
61+ // Using a unique_lock instead of lock_guard to avoid deadlocks and instead, gracefully fail
62+ std::unique_lock<std::mutex> ul{system_state_cookie_store_guard, std::try_to_lock};
63+ if (ul.owns_lock())
64+ sp->system_state_cookie_store[state] = result.value();
65+ else
66+ std::cerr << "Failed to lock system_state_cookie_store_guard and update system lock state" << std::endl;
67+ }
68
69- sp->system_state_cookie_store[state] = result.value();
70 sp->signals.acquired(state);
71 }
72 }, std::string{wake_lock_name}, static_cast<std::int32_t>(state));
73@@ -240,23 +264,42 @@
74 if (state == media::power::SystemState::suspend)
75 return;
76
77- std::lock_guard<std::mutex> lg{system_state_cookie_store_guard};
78-
79- if (system_state_cookie_store.count(state) == 0)
80- return;
81+ // Tighten the scope on the unique_lock
82+ {
83+ // Using a unique_lock instead of lock_guard to avoid deadlocks and instead, gracefully fail
84+ std::unique_lock<std::mutex> ul{system_state_cookie_store_guard, std::try_to_lock};
85+ if (ul.owns_lock())
86+ {
87+ if (system_state_cookie_store.count(state) == 0)
88+ return;
89+ }
90+ else
91+ {
92+ std::cerr << "Failed to lock system_state_cookie_store_guard and check system lock state" << std::endl;
93+ // Prevent system_state_cookie_store.count(state) and the actual call to clearSysState below from
94+ // getting out of sync.
95+ return;
96+ }
97+ }
98
99 std::weak_ptr<SystemStateLock> wp{shared_from_this()};
100
101- object->invoke_method_asynchronously_with_callback<com::canonical::powerd::Interface::clearSysState, void>([wp, state](const core::dbus::Result<void>& result)
102+ object->invoke_method_asynchronously_with_callback<com::canonical::powerd::Interface::clearSysState, void>([this, wp, state](const core::dbus::Result<void>& result)
103 {
104 if (result.is_error())
105 std::cerr << result.error().print() << std::endl;
106
107 if (auto sp = wp.lock())
108 {
109- std::lock_guard<std::mutex> lg{sp->system_state_cookie_store_guard};
110+ // Tighten the scope on the unique_lock
111+ {
112+ std::unique_lock<std::mutex> ul{system_state_cookie_store_guard, std::try_to_lock};
113+ if (ul.owns_lock())
114+ sp->system_state_cookie_store.erase(state);
115+ else
116+ std::cerr << "Failed to lock system_state_cookie_store_guard and erase system lock state" << std::endl;
117+ }
118
119- sp->system_state_cookie_store.erase(state);
120 sp->signals.released(state);
121 }
122 }, system_state_cookie_store.at(state));

Subscribers

People subscribed via source and target branches

to all changes: