Mir

Merge lp:mir/0.19 into lp:mir/ubuntu

Proposed by kevin gunn on 2016-02-02
Status: Merged
Approved by: kevin gunn on 2016-02-05
Approved revision: 3289
Merged at revision: 1257
Proposed branch: lp:mir/0.19
Merge into: lp:mir/ubuntu
Diff against target: 659 lines (+245/-160)
11 files modified
CMakeLists.txt (+1/-1)
debian/changelog (+88/-34)
src/client/probing_client_platform_factory.cpp (+24/-23)
src/common/sharedlibrary/CMakeLists.txt (+1/-1)
src/common/sharedlibrary/shared_library_prober.cpp (+20/-5)
src/common/symbols.map (+8/-1)
src/include/common/mir/shared_library_prober.h (+8/-0)
src/server/compositor/multi_threaded_compositor.cpp (+80/-79)
src/server/input/default_input_manager.cpp (+12/-4)
tests/acceptance-tests/test_prompt_session_client_api.cpp (+1/-1)
tests/unit-tests/compositor/test_multi_threaded_compositor.cpp (+2/-11)
To merge this branch: bzr merge lp:mir/0.19
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve on 2016-02-05
Mir development team 2016-02-02 Pending
Review via email: mp+284772@code.launchpad.net

Commit Message

Mir 0.19.1 - reliability and debugging update

Description of the Change

.

To post a comment you must log in.
Daniel van Vugt (vanvugt) wrote :

I've added a critical fix from trunk. Although it required a questionable new symbols.map stanza. Needs sanity-checking.

lp:mir/0.19 updated on 2016-02-03
3287. By Daniel van Vugt on 2016-02-03

Typo

PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:3287
http://jenkins.qa.ubuntu.com/job/mir-ubuntu-ci/127/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-vivid-i386-build/5778
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-vivid-amd64-build/4685
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-vivid-touch/5734
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-xenial-touch/372
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-amd64-ci/15
        deb: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-amd64-ci/15/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-i386-ci/15
        deb: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-i386-ci/15/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5731
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5731/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-touch/8143
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27261
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/368
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/368/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-xenial-touch/224
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27264

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-ubuntu-ci/127/rebuild

review: Approve (continuous-integration)
lp:mir/0.19 updated on 2016-02-04
3288. By Daniel van Vugt on 2016-02-04

debian/changelog: s/loggging/loggging/

PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:3288
http://jenkins.qa.ubuntu.com/job/mir-ubuntu-ci/129/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-vivid-i386-build/5797
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-vivid-amd64-build/4704
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-vivid-touch/5753
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-xenial-touch/384
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-amd64-ci/17
        deb: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-amd64-ci/17/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-i386-ci/17
        deb: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-i386-ci/17/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5750
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5750/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-touch/8160
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27304
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/380
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/380/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-xenial-touch/234
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27305

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-ubuntu-ci/129/rebuild

review: Approve (continuous-integration)
lp:mir/0.19 updated on 2016-02-04
3289. By kevin gunn on 2016-02-04

disable tests/acceptance-tests/test_prompt_session_client_api.cpp due to bug 1540731

PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:3289
http://jenkins.qa.ubuntu.com/job/mir-ubuntu-ci/130/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-vivid-i386-build/5810
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-vivid-amd64-build/4717
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-vivid-touch/5766
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-xenial-touch/391/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-amd64-ci/18
        deb: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-amd64-ci/18/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-i386-ci/18
        deb: http://jenkins.qa.ubuntu.com/job/mir-ubuntu-xenial-i386-ci/18/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5763
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5763/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-touch/8171
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27343
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/387
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/387/artifact/work/output/*zip*/output.zip
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-xenial-touch/241/console
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/27345

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-ubuntu-ci/130/rebuild

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-01-26 06:52:31 +0000
3+++ CMakeLists.txt 2016-02-04 21:06:45 +0000
4@@ -28,7 +28,7 @@
5
6 set(MIR_VERSION_MAJOR 0)
7 set(MIR_VERSION_MINOR 19)
8-set(MIR_VERSION_PATCH 0)
9+set(MIR_VERSION_PATCH 1)
10
11 add_definitions(-DMIR_VERSION_MAJOR=${MIR_VERSION_MAJOR})
12 add_definitions(-DMIR_VERSION_MINOR=${MIR_VERSION_MINOR})
13
14=== modified file 'debian/changelog'
15--- debian/changelog 2016-01-28 12:19:47 +0000
16+++ debian/changelog 2016-02-04 21:06:45 +0000
17@@ -1,42 +1,96 @@
18+mir (0.19.1-0ubuntu1) UNRELEASED; urgency=medium
19+
20+ [ Kevin Gunn ]
21+ * New upstream release 0.19.1 (https://launchpad.net/mir/+milestone/0.19.1)
22+ - Improved reporting to assist in critical debug
23+ - Improved on the fix for LP: #1527449 and LP: #1526658 in order to
24+ avoid Unity8 crashing on upgraded xenial desktops.
25+
26+ -- Kevin Gunn <kevin.gunn@canonical.com> Tue, 02 Feb 2016 11:59:26 -0600
27+
28 mir (0.19.0+16.04.20160128-0ubuntu1) xenial; urgency=medium
29
30 [ Brandon Schaefer ]
31- * New upstream release 0.19.0
32- - API summary:
33- . mirclient abi unchanged at 9
34- . mirserver abi bumped to 37
35- . mircommon abi unchanged at 5
36- . mirplatform abi unchanged at 11
37- . mirprotobuf abi unchanged at 3
38- . mirplatformgraphics abi bumped to 7
39- . mirclientplatform abi bumped to 4
40- . mirinputplatform abi bumped to 5
41- . mircookie abi bumped to 2
42- - Bug fix:
43- . Mir servers crash on mouse input (LP: #1528438)
44- . Pinch to zoom not working reliably (LP: #1531517)
45- . Passing DisplayConfiguration scale property from
46- nested server to host appears to not work (LP: #1535780)
47- . Various TSan reports when running test suite
48- on a mir tsan enabled build (LP: #1523647)
49- . Buffer leak during repeated mirscreencasts
50- causes server to be killed (LP: #1523900)
51- . Cursor now displays correctly (LP: #1526779)
52- .ProgramOption::parse_file() reports problems to cerr (LP: #1190165)
53- . Nested servers can select wrong platform (LP: #1515558)
54- . There seems to be missing RTTI information
55- when linking with UBSan enabled (LP: #1521930)
56+ * New upstream release 0.19.0 (https://launchpad.net/mir/+milestone/0.19.0)
57+ - ABI summary:
58+ . mirclient ABI unchanged at 9
59+ . mirserver ABI bumped to 37
60+ . mircommon ABI unchanged at 5
61+ . mirplatform ABI unchanged at 11
62+ . mirprotobuf ABI unchanged at 3
63+ . mirplatformgraphics ABI bumped to 7
64+ . mirclientplatform ABI bumped to 4
65+ . mirinputplatform ABI bumped to 5
66+ . mircookie ABI bumped to 2
67+ - Enhancements:
68+ . Improve compositor start logging
69+ . Mir cookie support added for copy paste use
70+ - Bugs fixed:
71+ . [regression] Mir servers crash on mouse input -
72+ std::exception::what: Client input channel write blocked : 11,
73+ "Resource temporarily unavailable" (LP: #1528438)
74+ . [regression] pinch to zoom not working reliably (LP: #1531517)
75+ . Passing DisplayConfiguration scale property from nested server to host
76+ appears to not work (LP: #1535780)
77+ . [enhancement] Support copy-paste between X and Mir (LP: #1471998)
78+ . Various TSan reports when running test suite on a mir tsan enabled
79+ build (LP: #1523647)
80+ . [testsfail] Intermittent failure in
81+ TestClientInput.clients_receive_relative_pointer_events (LP: #1523872)
82+ . Buffer leak during repeated mirscreencasts causes server to be killed
83+ (LP: #1523900)
84+ . Mir clients (including Unity8 itself) crash in XGetXCBConnection() if
85+ multiple versions of mir-client-platform-mesa are installed.
86+ (LP: #1526658)
87+ . Cursor displayed incorrectly (looks like incorrect stride)
88+ (LP: #1526779)
89+ . [regression] Mir servers just segfault just after "Selected driver:"
90+ instead of reporting exceptions (LP: #1528135)
91+ . Setting a surface keymap crashes in xkbcommon:
92+ xkb_keymap_new_from_names() (LP: #1530946)
93+ . [enhancement] Implement support for QWindow::visibility set to
94+ Automatic (LP: #1535397)
95+ . ProgramOption::parse_file() reports problems to cerr (LP: #1190165)
96+ . Dynamic double buffering fails to detect inertial dash scrolling as
97+ slow; and stutters instead of scaling up to triple buffers.
98+ (LP: #1476201)
99+ . CI Failures: ClientLatency.throttled_input_rate_yields_lower_latency
100+ (LP: #1509291)
101+ . [regression] Nested servers can select wrong platform (LP: #1515558)
102+ . "there seems to be missing RTTI information when linking with UBSan
103+ enabled" (LP: #1521930)
104 . Mir threadsanitizer build fails with GCC (LP: #1522581)
105- . After "make install" mir_demo_server cannot
106- find shared object file in /usr/local/lib (LP: #1522836)
107- . Fixed a test in TestClientInput (LP: #1523965)
108- . Mir servers choose graphics-dummy (or no driver at all)
109+ . After "make install" mir_demo_server cannot find shared object file in
110+ /usr/local/lib (LP: #1522836)
111+ . [testfail] Intermittent failure in TestClientInput.clients_receive_
112+ pointer_within_coordinate_system_of_window (LP: #1523965)
113+ . [regression] [ FAILED ]
114+ ClientSurfaceEvents.surface_receives_output_event_on_creation
115+ (LP: #1524161)
116+ . [ FAILED ] TestClientInput.scene_obscure_motion_events_by_stacking
117+ (LP: #1524230)
118+ . There's something racy in ServerDisconnect.is_detected_by_client
119+ (LP: #1526248)
120+ . Mir clients leak all driver modules including the unused ones, keeping
121+ them resident (LP: #1527449)
122+ . [regression] Mir servers choose graphics-dummy (or no driver at all)
123 over mesa-kms on a desktop (LP: #1528082)
124- . Function mir_event_get_close_surface_event is never used (LP: #1447690)
125- . mir::input::Surface::consume(MirEvent const& event)
126- should not take a reference to an opaque type (LP: #1450797)
127- . lintian: E: mir-doc: privacy-breach-logo (LP: #1483471)
128-
129+ . Function 'mir_event_get_close_surface_event' is never used
130+ (LP: #1447690)
131+ . mir::input::Surface::consume(MirEvent const& event) should not take a
132+ reference to an opaque type (LP: #1450797)
133+ . lintian: E: mir-doc: privacy-breach-logo
134+ usr/share/doc/mir-doc/html/cppguide/index.html
135+ (http://www.google.com/favicon.ico) (LP: #1483471)
136+ . lintian: W: mir-doc: embedded-javascript-library
137+ usr/share/doc/mir-doc/html/jquery.js please use libjs-jquery
138+ (LP: #1483472)
139+ . lintian: E: mir-test-tools:
140+ arch-dependent-file-not-in-arch-specific-directory (LP: #1483475)
141+ . incorrect reporting in mf::SessionMediator::release_buffer_stream()
142+ (LP: #1499777)
143+ . [testsfail] Segmentation fault SystemCompositorWindowManager.
144+ if_a_surface_posts_client_gets_focus (LP: #1522356)
145
146 [ CI Train Bot ]
147 * No-change rebuild.
148
149=== modified file 'src/client/probing_client_platform_factory.cpp'
150--- src/client/probing_client_platform_factory.cpp 2016-01-20 23:59:18 +0000
151+++ src/client/probing_client_platform_factory.cpp 2016-02-04 21:06:45 +0000
152@@ -31,6 +31,25 @@
153 // than it takes to choose the right one. So this list is local:
154 std::vector<std::shared_ptr<mir::SharedLibrary>> platform_modules;
155
156+ auto const module_selector = [context, &platform_modules](std::shared_ptr<mir::SharedLibrary> const& module)
157+ {
158+ try
159+ {
160+ auto probe = module->load_function<ClientPlatformProbe>("is_appropriate_module", CLIENT_PLATFORM_VERSION);
161+ if (probe(context))
162+ {
163+ platform_modules.push_back(module);
164+ return Selection::quit;
165+ }
166+ }
167+ catch (std::runtime_error const&)
168+ {
169+ // Assume we were handed a SharedLibrary that's not a client platform module of the correct vintage.
170+ }
171+
172+ return Selection::persist;
173+ };
174+
175 if (!platform_overrides.empty())
176 {
177 // Even forcing a choice, platform is only loaded on demand. It's good
178@@ -39,37 +58,19 @@
179 // if you really wanted to.
180
181 for (auto const& platform : platform_overrides)
182- platform_modules.push_back(
183- std::make_shared<mir::SharedLibrary>(platform));
184+ module_selector(std::make_shared<mir::SharedLibrary>(platform));
185 }
186 else
187 {
188 for (auto const& path : platform_paths)
189- {
190- // This is sub-optimal. We shouldn't need to have all drivers
191- // loaded simultaneously, but we do for now due to this API:
192- auto modules = mir::libraries_for_path(path,
193- *shared_library_prober_report);
194- for (auto const& module : modules)
195- platform_modules.push_back(module);
196- }
197+ select_libraries_for_path(path, module_selector, *shared_library_prober_report);
198 }
199
200 for (auto& module : platform_modules)
201 {
202- try
203- {
204- auto probe = module->load_function<mir::client::ClientPlatformProbe>("is_appropriate_module", CLIENT_PLATFORM_VERSION);
205- if (probe(context))
206- {
207- auto factory = module->load_function<mir::client::CreateClientPlatform>("create_client_platform", CLIENT_PLATFORM_VERSION);
208- return factory(context);
209- }
210- }
211- catch(std::runtime_error const&)
212- {
213- // We were handed a SharedLibrary that's not a client platform module?
214- }
215+ auto factory = module->load_function<CreateClientPlatform>("create_client_platform", CLIENT_PLATFORM_VERSION);
216+ return factory(context);
217 }
218+
219 BOOST_THROW_EXCEPTION(std::runtime_error{"No appropriate client platform module found"});
220 }
221
222=== modified file 'src/common/sharedlibrary/CMakeLists.txt'
223--- src/common/sharedlibrary/CMakeLists.txt 2016-01-20 23:59:18 +0000
224+++ src/common/sharedlibrary/CMakeLists.txt 2016-02-04 21:06:45 +0000
225@@ -17,7 +17,7 @@
226 add_library(mirsharedsharedlibrary OBJECT
227 module_deleter.cpp
228 shared_library.cpp
229- shared_library_prober.cpp
230+ shared_library_prober.cpp ${PROJECT_SOURCE_DIR}/src/include/common/mir/shared_library_prober.h
231 )
232
233 list(APPEND MIR_COMMON_SOURCES
234
235=== modified file 'src/common/sharedlibrary/shared_library_prober.cpp'
236--- src/common/sharedlibrary/shared_library_prober.cpp 2016-01-20 23:59:18 +0000
237+++ src/common/sharedlibrary/shared_library_prober.cpp 2016-02-04 21:06:45 +0000
238@@ -63,8 +63,10 @@
239 }
240 }
241
242-std::vector<std::shared_ptr<mir::SharedLibrary>>
243-mir::libraries_for_path(std::string const& path, mir::SharedLibraryProberReport& report)
244+void mir::select_libraries_for_path(
245+ std::string const& path,
246+ std::function<Selection(std::shared_ptr<mir::SharedLibrary> const&)> const& selector,
247+ mir::SharedLibraryProberReport& report)
248 {
249 report.probing_path(path);
250 // We use the error_code overload because we want to throw a std::system_error
251@@ -87,20 +89,33 @@
252
253 std::sort(libraries.begin(), libraries.end(), &greater_soname_version);
254
255- std::vector<std::shared_ptr<mir::SharedLibrary>> result;
256-
257 for(auto& lib : libraries)
258 {
259 try
260 {
261 report.loading_library(lib);
262- result.emplace_back(std::make_shared<mir::SharedLibrary>(lib.string()));
263+ auto const shared_lib = std::make_shared<mir::SharedLibrary>(lib.string());
264+
265+ if (selector(shared_lib) == Selection::quit)
266+ return;
267 }
268 catch (std::runtime_error const& err)
269 {
270 report.loading_failed(lib, err);
271 }
272 }
273+}
274+
275+std::vector<std::shared_ptr<mir::SharedLibrary>>
276+mir::libraries_for_path(std::string const& path, mir::SharedLibraryProberReport& report)
277+{
278+ std::vector<std::shared_ptr<mir::SharedLibrary>> result;
279+
280+ select_libraries_for_path(
281+ path,
282+ [&](std::shared_ptr<mir::SharedLibrary> const& shared_lib)
283+ { result.push_back(shared_lib); return Selection::persist; },
284+ report);
285
286 return result;
287 }
288
289=== modified file 'src/common/symbols.map'
290--- src/common/symbols.map 2016-01-27 19:42:57 +0000
291+++ src/common/symbols.map 2016-02-04 21:06:45 +0000
292@@ -201,7 +201,7 @@
293 local: *;
294 } MIR_COMMON_5;
295
296-MIR_COMMON_5v19 { # New functions in Mir 0.19
297+MIR_COMMON_5v19 { # New functions in Mir 0.19.0
298 global:
299 extern "C++" {
300 typeinfo?for?mir::logging::SharedLibraryProberReport;
301@@ -211,3 +211,10 @@
302 mir::detail::libname_impl*;
303 };
304 } MIR_COMMON_5.1;
305+
306+MIR_COMMON_0.19.1 { # New functions in Mir 0.19.1
307+ global:
308+ extern "C++" {
309+ mir::select_libraries_for_path*;
310+ };
311+} MIR_COMMON_5v19; # <- Note Mir 0.19.0 used the wrong syntax
312
313=== modified file 'src/include/common/mir/shared_library_prober.h'
314--- src/include/common/mir/shared_library_prober.h 2015-02-22 07:46:25 +0000
315+++ src/include/common/mir/shared_library_prober.h 2016-02-04 21:06:45 +0000
316@@ -30,6 +30,14 @@
317 class SharedLibrary;
318
319 std::vector<std::shared_ptr<SharedLibrary>> libraries_for_path(std::string const& path, SharedLibraryProberReport& report);
320+
321+// The selector can tell select_libraries_for_path() to persist or quit after each library
322+enum class Selection { persist, quit };
323+
324+void select_libraries_for_path(
325+ std::string const& path,
326+ std::function<Selection(std::shared_ptr<SharedLibrary> const&)> const& selector,
327+ SharedLibraryProberReport& report);
328 }
329
330
331
332=== modified file 'src/server/compositor/multi_threaded_compositor.cpp'
333--- src/server/compositor/multi_threaded_compositor.cpp 2016-01-20 23:59:18 +0000
334+++ src/server/compositor/multi_threaded_compositor.cpp 2016-02-04 21:06:45 +0000
335@@ -1,5 +1,5 @@
336 /*
337- * Copyright © 2013-2015 Canonical Ltd.
338+ * Copyright © 2013-2016 Canonical Ltd.
339 *
340 * This program is free software: you can redistribute it and/or modify it
341 * under the terms of the GNU General Public License version 3,
342@@ -110,81 +110,82 @@
343
344 started.set_value();
345
346- std::unique_lock<std::mutex> lock{run_mutex};
347- while (running)
348+ try
349 {
350- /* Wait until compositing has been scheduled or we are stopped */
351- run_cv.wait(lock, [&]{ return (frames_scheduled > 0) || !running; });
352-
353- /*
354- * Check if we are running before compositing, since we may have
355- * been stopped while waiting for the run_cv above.
356- */
357- if (running)
358+ std::unique_lock<std::mutex> lock{run_mutex};
359+ while (running)
360 {
361- /*
362- * Each surface could have a number of frames ready in its buffer
363- * queue. And we need to ensure that we render all of them so that
364- * none linger in the queue indefinitely (seen as input lag).
365- * frames_scheduled indicates the number of frames that are scheduled
366- * to ensure all surfaces' queues are fully drained.
367- */
368- frames_scheduled--;
369- lock.unlock();
370-
371- for (auto& tuple : compositors)
372- {
373- auto& compositor = std::get<1>(tuple);
374- compositor->composite(scene->scene_elements_for(compositor.get()));
375- }
376- group.post();
377-
378- /*
379- * "Predictive bypass" optimization: If the last frame was
380- * bypassed/overlayed or you simply have a fast GPU, it is
381- * beneficial to sleep for most of the next frame. This reduces
382- * the latency between snapshotting the scene and post()
383- * completing by almost a whole frame.
384- */
385- auto delay = force_sleep >= std::chrono::milliseconds::zero() ?
386- force_sleep : group.recommended_sleep();
387- std::this_thread::sleep_for(delay);
388-
389- lock.lock();
390-
391- /*
392- * Note the compositor may have chosen to ignore any number
393- * of renderables and not consumed buffers from them. So it's
394- * important to re-count number of frames pending, separately
395- * to the initial scene_elements_for()...
396- */
397- int pending = 0;
398- for (auto& compositor : compositors)
399- {
400- auto const comp_id = std::get<1>(compositor).get();
401- int pend = scene->frames_pending(comp_id);
402- if (pend > pending)
403- pending = pend;
404- }
405-
406- if (pending > frames_scheduled)
407- frames_scheduled = pending;
408+ /* Wait until compositing has been scheduled or we are stopped */
409+ run_cv.wait(lock, [&]{ return (frames_scheduled > 0) || !running; });
410+
411+ /*
412+ * Check if we are running before compositing, since we may have
413+ * been stopped while waiting for the run_cv above.
414+ */
415+ if (running)
416+ {
417+ /*
418+ * Each surface could have a number of frames ready in its buffer
419+ * queue. And we need to ensure that we render all of them so that
420+ * none linger in the queue indefinitely (seen as input lag).
421+ * frames_scheduled indicates the number of frames that are scheduled
422+ * to ensure all surfaces' queues are fully drained.
423+ */
424+ frames_scheduled--;
425+ lock.unlock();
426+
427+ for (auto& tuple : compositors)
428+ {
429+ auto& compositor = std::get<1>(tuple);
430+ compositor->composite(scene->scene_elements_for(compositor.get()));
431+ }
432+ group.post();
433+
434+ /*
435+ * "Predictive bypass" optimization: If the last frame was
436+ * bypassed/overlayed or you simply have a fast GPU, it is
437+ * beneficial to sleep for most of the next frame. This reduces
438+ * the latency between snapshotting the scene and post()
439+ * completing by almost a whole frame.
440+ */
441+ auto delay = force_sleep >= std::chrono::milliseconds::zero() ?
442+ force_sleep : group.recommended_sleep();
443+ std::this_thread::sleep_for(delay);
444+
445+ lock.lock();
446+
447+ /*
448+ * Note the compositor may have chosen to ignore any number
449+ * of renderables and not consumed buffers from them. So it's
450+ * important to re-count number of frames pending, separately
451+ * to the initial scene_elements_for()...
452+ */
453+ int pending = 0;
454+ for (auto& compositor : compositors)
455+ {
456+ auto const comp_id = std::get<1>(compositor).get();
457+ int pend = scene->frames_pending(comp_id);
458+ if (pend > pending)
459+ pending = pend;
460+ }
461+
462+ if (pending > frames_scheduled)
463+ frames_scheduled = pending;
464+ }
465 }
466 }
467+ catch (...)
468+ {
469+ mir::terminate_with_current_exception();
470+ }
471 }
472 catch(...)
473 {
474- try
475- {
476- //Move the promise so that the promise destructor occurs here rather than in the thread
477- //destroying CompositingFunctor, mostly to appease TSan
478- auto promise = std::move(started);
479- promise.set_exception(std::current_exception());
480- }
481- catch(...)
482- {
483- }
484- mir::terminate_with_current_exception();
485+ started.set_exception(std::current_exception());
486+
487+ //Move the promise so that the promise destructor occurs here rather than in the thread
488+ //destroying CompositingFunctor, mostly to appease TSan
489+ auto promise = std::move(started);
490 }
491
492 void schedule_compositing(int num_frames)
493@@ -209,6 +210,8 @@
494 {
495 if (started_future.wait_for(10s) != std::future_status::ready)
496 BOOST_THROW_EXCEPTION(std::runtime_error("Compositor thread failed to start"));
497+
498+ started_future.get();
499 }
500
501 private:
502@@ -273,7 +276,7 @@
503 void mc::MultiThreadedCompositor::start()
504 {
505 auto stopped = CompositorState::stopped;
506-
507+
508 if (!state.compare_exchange_strong(stopped, CompositorState::starting))
509 return;
510
511@@ -281,7 +284,7 @@
512
513 /* To cleanup state if any code below throws */
514 auto cleanup_if_unwinding = on_unwind(
515- [this]{ destroy_compositing_threads(); });
516+ [this]{ destroy_compositing_threads(); state = CompositorState::stopped; });
517
518 create_compositing_threads();
519
520@@ -291,6 +294,8 @@
521 /* Optional first render */
522 if (compose_on_start)
523 schedule_compositing(1);
524+
525+ state = CompositorState::started;
526 }
527
528 void mc::MultiThreadedCompositor::stop()
529@@ -300,8 +305,6 @@
530 if (!state.compare_exchange_strong(started, CompositorState::stopping))
531 return;
532
533- state = CompositorState::stopping;
534-
535 /* To cleanup state if any code below throws */
536 auto cleanup_if_unwinding = on_unwind(
537 [this]{ state = CompositorState::started; });
538@@ -314,6 +317,10 @@
539 // If the compositor is restarted we've likely got clients blocked
540 // so we will need to schedule compositing immediately
541 compose_on_start = true;
542+
543+ report->stopped();
544+
545+ state = CompositorState::stopped;
546 }
547
548 void mc::MultiThreadedCompositor::create_compositing_threads()
549@@ -333,8 +340,6 @@
550
551 for (auto& functor : thread_functors)
552 functor->wait_until_started();
553-
554- state = CompositorState::started;
555 }
556
557 void mc::MultiThreadedCompositor::destroy_compositing_threads()
558@@ -347,8 +352,4 @@
559
560 thread_functors.clear();
561 futures.clear();
562-
563- report->stopped();
564-
565- state = CompositorState::stopped;
566 }
567
568=== modified file 'src/server/input/default_input_manager.cpp'
569--- src/server/input/default_input_manager.cpp 2016-01-20 23:59:18 +0000
570+++ src/server/input/default_input_manager.cpp 2016-02-04 21:06:45 +0000
571@@ -70,10 +70,14 @@
572 if (!state.compare_exchange_strong(expected, State::starting))
573 return;
574
575- auto reset_to_stopped_on_failure = on_unwind([this]{state = State::stopped;});
576+ auto reset_to_stopped_on_failure = on_unwind([this]
577+ {
578+ auto expected = State::starting;
579+ state.compare_exchange_strong(expected, State::stopped);
580+ });
581
582 multiplexer->add_watch(queue);
583- auto unregister_queue = on_unwind([this]{multiplexer->remove_watch(queue);});
584+ auto unregister_queue = on_unwind([this]{ if (state == State::starting) multiplexer->remove_watch(queue);});
585
586
587 auto started_promise = std::make_shared<std::promise<void>>();
588@@ -114,7 +118,11 @@
589 if (!state.compare_exchange_strong(expected, State::stopping))
590 return;
591
592- auto reset_to_started_on_failure = on_unwind([this]{state = State::started;});
593+ auto reset_to_started_on_failure = on_unwind([this]
594+ {
595+ auto expected = State::stopping;
596+ state.compare_exchange_strong(expected, State::started);
597+ });
598
599 auto const stop_promise = std::make_shared<std::promise<void>>();
600
601@@ -129,7 +137,7 @@
602 auto restore_platforms = on_unwind(
603 [this]
604 {
605- queue->enqueue([this](){ start_platforms(); });
606+ if (state == State::stopping) queue->enqueue([this](){ start_platforms(); });
607 });
608
609 multiplexer->remove_watch(queue);
610
611=== modified file 'tests/acceptance-tests/test_prompt_session_client_api.cpp'
612--- tests/acceptance-tests/test_prompt_session_client_api.cpp 2016-01-20 23:59:18 +0000
613+++ tests/acceptance-tests/test_prompt_session_client_api.cpp 2016-02-04 21:06:45 +0000
614@@ -383,7 +383,7 @@
615 mir_prompt_session_release_sync(prompt_session);
616 }
617
618-TEST_F(PromptSessionClientAPI, client_pid_is_associated_with_session)
619+TEST_F(PromptSessionClientAPI, DISABLED_client_pid_is_associated_with_session)
620 {
621 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
622
623
624=== modified file 'tests/unit-tests/compositor/test_multi_threaded_compositor.cpp'
625--- tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2016-01-20 23:59:18 +0000
626+++ tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2016-02-04 21:06:45 +0000
627@@ -889,7 +889,7 @@
628 compositor.stop();
629 }
630
631-TEST(MultiThreadedCompositor, does_not_block_in_start_when_compositor_thread_fails)
632+TEST(MultiThreadedCompositor, when_compositor_thread_fails_start_reports_error)
633 {
634 using namespace testing;
635 unsigned int const nbuffers{3};
636@@ -899,22 +899,13 @@
637 auto db_compositor_factory = std::make_shared<mtd::NullDisplayBufferCompositorFactory>();
638 auto mock_report = std::make_shared<testing::NiceMock<mtd::MockCompositorReport>>();
639
640- // Ignore SIGTERM. We must keep ignoring SIGTERM until the compositor is
641- // destroyed/stopped (hence sigterm_raii must be created before the compositor),
642- // since even after compositor.start() has returned because of an error the
643- // compositing threads may not have finished and could emit SIGTERM.
644- sighandler_t old_sigterm_handler = nullptr;
645- auto const sigterm_raii = mir::raii::paired_calls(
646- [&] { old_sigterm_handler = signal(SIGTERM, SIG_IGN); },
647- [&] { signal(SIGTERM, old_sigterm_handler); });
648-
649 mc::MultiThreadedCompositor compositor{
650 display, stub_scene, db_compositor_factory, mock_display_listener, mock_report, default_delay, true};
651
652 EXPECT_CALL(*mock_display_listener, add_display(_))
653 .WillRepeatedly(Throw(std::runtime_error("Failed to add display")));
654
655- compositor.start();
656+ EXPECT_THROW(compositor.start(), std::runtime_error);
657 }
658
659 //LP: 1481418

Subscribers

People subscribed via source and target branches

to all changes: