Mir

Merge lp:~raof/mir/wayland-clients-close-their-sessions-on-quit into lp:mir

Proposed by Chris Halse Rogers on 2017-09-26
Status: Merged
Merged at revision: 4270
Proposed branch: lp:~raof/mir/wayland-clients-close-their-sessions-on-quit
Merge into: lp:mir
Prerequisite: lp:~raof/mir/wayland-input-fixes
Diff against target: 224 lines (+62/-64)
1 file modified
src/server/frontend/wayland/wayland_connector.cpp (+62/-64)
To merge this branch: bzr merge lp:~raof/mir/wayland-clients-close-their-sessions-on-quit
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Needs Fixing on 2017-09-26
Alan Griffiths 2017-09-26 Approve on 2017-09-26
Review via email: mp+331358@code.launchpad.net

Commit message

Wayland: Close the Mir session on client quit.

Fixes phantom sessions hanging around after client quit.

Fixes: https://bugs.launchpad.net/mir/+bug/1719586

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

Looks sensible and seems to work.

review: Approve
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Autolanding.
More details in the following jenkins job:
https://mir-jenkins.ubuntu.com/job/mir-autolanding/1443/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/5064/console
    None: https://mir-jenkins.ubuntu.com/job/generic-land-mp/1578/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5300
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5288
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5288
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5288
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/5108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/5108/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/5108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/5108/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/5108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/5108/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/5108/console
    ABORTED: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/5108/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/5108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/5108/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/5108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/5108/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/5108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/5108/artifact/output/*zip*/output.zip

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/server/frontend/wayland/wayland_connector.cpp'
2--- src/server/frontend/wayland/wayland_connector.cpp 2017-09-26 15:39:09 +0000
3+++ src/server/frontend/wayland/wayland_connector.cpp 2017-09-26 15:39:09 +0000
4@@ -158,8 +158,29 @@
5
6 struct ClientPrivate
7 {
8+ ClientPrivate(std::shared_ptr<mf::Session> const& session, mf::Shell& shell)
9+ : session{session},
10+ shell{&shell}
11+ {
12+ }
13+
14+ ~ClientPrivate()
15+ {
16+ shell->close_session(session);
17+ /*
18+ * This ensures that further calls to
19+ * wl_client_get_destroy_listener(client, &cleanup_private)
20+ * - and hence session_for_client(client) - return nullptr.
21+ */
22+ wl_list_remove(&destroy_listener.link);
23+ }
24+
25 wl_listener destroy_listener;
26- std::shared_ptr<mf::Session> session;
27+ std::shared_ptr<mf::Session> const session;
28+ /*
29+ * This shell is owned by the ClientSessionConstructor, which outlives all clients.
30+ */
31+ mf::Shell* const shell;
32 };
33
34 static_assert(
35@@ -182,9 +203,10 @@
36 {
37 auto listener = wl_client_get_destroy_listener(client, &cleanup_private);
38
39- assert(listener && "Client session requested for malformed client");
40+ if (listener)
41+ return private_from_listener(listener)->session;
42
43- return private_from_listener(listener)->session;
44+ return nullptr;
45 }
46
47 struct ClientSessionConstructor
48@@ -220,9 +242,8 @@
49 "",
50 std::make_shared<WaylandEventSink>([](auto){}));
51
52- auto client_context = new ClientPrivate;
53+ auto client_context = new ClientPrivate{session, *construction_context->shell};
54 client_context->destroy_listener.notify = &cleanup_private;
55- client_context->session = session;
56 wl_client_add_destroy_listener(client, &client_context->destroy_listener);
57 }
58
59@@ -295,6 +316,19 @@
60
61 return buffer;
62 }
63+
64+template<typename Callable>
65+auto run_unless(std::shared_ptr<bool> const& condition, Callable&& callable)
66+{
67+ return
68+ [callable = std::move(callable), condition]()
69+ {
70+ if (*condition)
71+ return;
72+
73+ callable();
74+ };
75+}
76 }
77
78 class WlShmBuffer :
79@@ -511,7 +545,8 @@
80 allocator{allocator},
81 executor{executor},
82 pending_buffer{nullptr},
83- pending_frames{std::make_shared<std::vector<wl_resource*>>()}
84+ pending_frames{std::make_shared<std::vector<wl_resource*>>()},
85+ destroyed{std::make_shared<bool>(false)}
86 {
87 auto session = session_for_client(client);
88 mg::BufferProperties const props{
89@@ -527,6 +562,13 @@
90 stream->allow_framedropping(true);
91 }
92
93+ ~WlSurface()
94+ {
95+ *destroyed = true;
96+ if (auto session = session_for_client(client))
97+ session->destroy_buffer_stream(stream_id);
98+ }
99+
100 void set_resize_handler(std::function<void(geom::Size)> const& handler)
101 {
102 resize_handler = handler;
103@@ -548,6 +590,7 @@
104
105 wl_resource* pending_buffer;
106 std::shared_ptr<std::vector<wl_resource*>> const pending_frames;
107+ std::shared_ptr<bool> const destroyed;
108
109 void destroy();
110 void attach(std::experimental::optional<wl_resource*> const& buffer, int32_t x, int32_t y);
111@@ -620,9 +663,10 @@
112 std::shared_ptr<mg::Buffer> mir_buffer;
113 auto shm_buffer = wl_shm_buffer_get(pending_buffer);
114 auto send_frame_notifications =
115- [executor = executor, frames = pending_frames]()
116+ [executor = executor, frames = pending_frames, destroyed = destroyed]()
117 {
118- executor->spawn(
119+ executor->spawn(run_unless(
120+ destroyed,
121 [frames]()
122 {
123 /*
124@@ -639,7 +683,7 @@
125 wl_resource_destroy(frame);
126 }
127 frames->clear();
128- });
129+ }));
130 };
131
132 if (shm_buffer)
133@@ -745,19 +789,6 @@
134 class WlPointer;
135 class WlTouch;
136
137-template<typename Callable>
138-auto run_unless(std::shared_ptr<bool> const& condition, Callable&& callable)
139-{
140- return
141- [callable = std::move(callable), condition]()
142- {
143- if (*condition)
144- return;
145-
146- callable();
147- };
148-}
149-
150 class WlKeyboard : public wayland::Keyboard
151 {
152 public:
153@@ -1555,15 +1586,15 @@
154 hide_spec.state = mir_window_state_hidden;
155 shell->modify_surface(session, id, hide_spec);
156 });
157-
158- auto shim = new DestructionShim{session, shell, surface_id};
159- shim->destruction_listener.notify = &cleanup_surface;
160- wl_resource_add_destroy_listener(
161- resource,
162- &shim->destruction_listener);
163- }
164-
165- ~WlShellSurface() override = default;
166+ }
167+
168+ ~WlShellSurface() override
169+ {
170+ if (auto session = session_for_client(client))
171+ {
172+ shell->destroy_surface(session, surface_id);
173+ }
174+ }
175 protected:
176 void pong(uint32_t /*serial*/) override
177 {
178@@ -1603,7 +1634,6 @@
179
180 auto const session = session_for_client(client);
181 shell->modify_surface(session, surface_id, mods);
182-
183 }
184
185 void set_popup(
186@@ -1636,38 +1666,6 @@
187 {
188 }
189 private:
190- struct DestructionShim
191- {
192- DestructionShim(
193- std::shared_ptr<mf::Session> const& session,
194- std::shared_ptr<mf::Shell> const& shell,
195- mf::SurfaceId id)
196- : session{session},
197- shell{shell},
198- surface_id{id}
199- {
200- }
201-
202- std::shared_ptr<mf::Session> const session;
203- std::shared_ptr<mf::Shell> const shell;
204- mf::SurfaceId const surface_id;
205- wl_listener destruction_listener;
206- };
207-
208- static_assert(
209- std::is_standard_layout<DestructionShim>::value,
210- "DestructionShim must be Standard Layout for wl_container_of to be defined behaviour");
211-
212- static void cleanup_surface(wl_listener* listener, void*)
213- {
214- DestructionShim* shim;
215- shim = wl_container_of(listener, shim, destruction_listener);
216-
217- shim->shell->destroy_surface(shim->session, shim->surface_id);
218-
219- delete shim;
220- }
221-
222 std::shared_ptr<mf::Shell> const shell;
223 mf::SurfaceId surface_id;
224 };

Subscribers

People subscribed via source and target branches