Skip to content

Commit 2594da6

Browse files
Use munmap() correctly (#213)
We were failing to release mmapped memory (doing it wrong and at the wrong time). That lead to the memory footprint growing without bound. C.f. canonical/mir#3710
2 parents 196d5c5 + 89d6d4d commit 2594da6

File tree

3 files changed

+20
-13
lines changed

3 files changed

+20
-13
lines changed

src/background_client.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,12 @@ void BackgroundClient::Self::draw_screen(SurfaceInfo& info, bool draws_crash) co
420420
info.output->output);
421421
}
422422

423-
if (info.buffer)
423+
if (info.buffer && info.buffer_size != stride * height)
424424
{
425-
wl_buffer_destroy(info.buffer);
425+
info.reset_buffer();
426426
}
427427

428+
if (!info.buffer)
428429
{
429430
auto const shm_pool = make_shm_pool(stride * height, &info.content_area);
430431

@@ -433,6 +434,7 @@ void BackgroundClient::Self::draw_screen(SurfaceInfo& info, bool draws_crash) co
433434
0,
434435
width, height, stride,
435436
WL_SHM_FORMAT_ARGB8888);
437+
info.buffer_size = stride * height;
436438
}
437439

438440
auto buffer = static_cast<unsigned char*>(info.content_area);

src/egfullscreenclient.cpp

+14-11
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ egmde::FullscreenClient::SurfaceInfo::~SurfaceInfo()
118118

119119
void egmde::FullscreenClient::SurfaceInfo::clear_window()
120120
{
121-
if (buffer)
122-
wl_buffer_destroy(buffer);
121+
reset_buffer();
123122

124123
if (shell_surface)
125124
wl_shell_surface_destroy(shell_surface);
@@ -128,11 +127,22 @@ void egmde::FullscreenClient::SurfaceInfo::clear_window()
128127
wl_surface_destroy(surface);
129128

130129

131-
buffer = nullptr;
132130
shell_surface = nullptr;
133131
surface = nullptr;
134132
}
135133

134+
void egmde::FullscreenClient::SurfaceInfo::reset_buffer()
135+
{
136+
if (buffer)
137+
{
138+
wl_buffer_destroy(buffer);
139+
if (munmap(content_area, buffer_size))
140+
mir::log_error("munmap() failed in %s: %s", __PRETTY_FUNCTION__, strerror(errno));
141+
buffer = nullptr;
142+
buffer_size = 0;
143+
}
144+
}
145+
136146
void egmde::FullscreenClient::Output::done(void* data, struct wl_output* /*wl_output*/)
137147
{
138148
auto const output = static_cast<Output*>(data);
@@ -261,12 +271,6 @@ void egmde::FullscreenClient::on_output_changed(Output const* output)
261271
auto const p = outputs.find(output);
262272
if (p != end(outputs))
263273
{
264-
if (auto& buffer = p->second.buffer)
265-
{
266-
wl_buffer_destroy(buffer);
267-
buffer = nullptr;
268-
}
269-
270274
draw_screen(p->second, should_draw_crash());
271275
}
272276

@@ -397,10 +401,9 @@ auto egmde::FullscreenClient::make_shm_pool(size_t size, void** data) const
397401

398402
return {
399403
wl_shm_create_pool(shm, fd, size),
400-
[size](auto* shm)
404+
[](auto* shm)
401405
{
402406
wl_shm_pool_destroy(shm);
403-
munmap(shm, size);
404407
}};
405408
}
406409

src/egfullscreenclient.h

+2
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ class FullscreenClient
131131
~SurfaceInfo();
132132

133133
void clear_window();
134+
void reset_buffer();
134135

135136
// Screen description
136137
Output const* output;
@@ -140,6 +141,7 @@ class FullscreenClient
140141
wl_surface* surface = nullptr;
141142
wl_shell_surface* shell_surface = nullptr;
142143
wl_buffer* buffer = nullptr;
144+
size_t buffer_size = 0;
143145
};
144146

145147
virtual void draw_screen(SurfaceInfo& info, bool draws_crash) const = 0;

0 commit comments

Comments
 (0)