Skip to content

Commit 36f7a1a

Browse files
author
Innes Anderson-Morrison
committed
sorting memory leak in Draw
1 parent dfaedf7 commit 36f7a1a

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

crates/penrose_ui/src/core/fontset.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ impl Drop for Fontset {
116116
// SAFETY: the Display we have a pointer to is freed by the parent draw
117117
unsafe {
118118
XftFontClose(self.dpy, self.primary.xfont);
119-
for f in self.fallback.drain(0..) {
119+
for f in self.fallback.drain(..) {
120120
XftFontClose(self.dpy, f.xfont);
121121
}
122122
}
@@ -214,7 +214,10 @@ impl Font {
214214
ext,
215215
);
216216

217-
Ok(((*ext).xOff as u32, self.h))
217+
let x_off = (*ext).xOff as u32;
218+
std::alloc::dealloc(ext as *mut u8, layout);
219+
220+
Ok((x_off, self.h))
218221
}
219222
}
220223

crates/penrose_ui/src/core/mod.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use std::{
2626
};
2727
use tracing::{debug, info};
2828
use x11::{
29-
xft::{XftColor, XftColorAllocName, XftDrawCreate, XftDrawStringUtf8},
29+
xft::{XftColor, XftColorAllocName, XftDraw, XftDrawCreate, XftDrawDestroy, XftDrawStringUtf8},
3030
xlib::{
3131
CapButt, Complex, CoordModeOrigin, Display, Drawable, False, JoinMiter, LineSolid, Window,
3232
XCopyArea, XCreateGC, XCreatePixmap, XDefaultColormap, XDefaultDepth, XDefaultVisual,
@@ -419,6 +419,8 @@ impl<'a> Context<'a> {
419419
) -> Result<(u32, u32)> {
420420
// SAFETY:
421421
// - the pointers for self.dpy and s.drawable are known to be non-null
422+
// - we wrap the returned pointer in DropXftDraw to ensure that we correctly destroy
423+
// the XftDraw we create here (see below)
422424
let d = unsafe {
423425
XftDrawCreate(
424426
self.dpy,
@@ -428,6 +430,8 @@ impl<'a> Context<'a> {
428430
)
429431
};
430432

433+
let _drop_draw = DropXftDraw { ptr: d };
434+
431435
let (lpad, rpad) = (padding.0 as i32, padding.1);
432436
let (mut x, y) = (lpad + self.dx, self.dy);
433437
let (mut total_w, mut total_h) = (x as u32, 0);
@@ -461,7 +465,22 @@ impl<'a> Context<'a> {
461465
total_h = max(total_h, chunk_h);
462466
}
463467

464-
Ok((total_w + rpad, total_h))
468+
return Ok((total_w + rpad, total_h));
469+
470+
// There are multiple error paths here where we need to make sure that we correctly destroy
471+
// the XftDraw we created. Rather than complicate the error handling we use a Drop wrapper
472+
// to ensure that we run XftDrawDestroy when the function returns.
473+
474+
struct DropXftDraw {
475+
ptr: *mut XftDraw,
476+
}
477+
478+
impl Drop for DropXftDraw {
479+
fn drop(&mut self) {
480+
// SAFETY: the pointer we have must be non-null
481+
unsafe { XftDrawDestroy(self.ptr) };
482+
}
483+
}
465484
}
466485

467486
/// Determine the width and height taken up by a given string in pixels.

0 commit comments

Comments
 (0)