mirror of https://github.com/adamdruppe/arsd.git
ketmar patch for xshm memory leak
This commit is contained in:
parent
83db6204da
commit
10d443e2e8
|
@ -4484,6 +4484,64 @@ version(X11) {
|
||||||
fprintf(stderr, "createXIM: XOpenIM failed!\n");
|
fprintf(stderr, "createXIM: XOpenIM failed!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for X11 we will keep all XShm-allocated images in this list, so we can free 'em on connection closing.
|
||||||
|
// we'll use glibc malloc()/free(), 'cause `unregisterImage()` can be called from object dtor.
|
||||||
|
static struct ImgList {
|
||||||
|
size_t img; // class; hide it from GC
|
||||||
|
ImgList* next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ImgList* imglist = null;
|
||||||
|
static bool imglistLocked = false; // true: don't register and unregister images
|
||||||
|
|
||||||
|
static void registerImage (Image img) {
|
||||||
|
if (!imglistLocked && img !is null) {
|
||||||
|
import core.stdc.stdlib : malloc;
|
||||||
|
auto it = cast(ImgList*)malloc(ImgList.sizeof);
|
||||||
|
assert(it !is null); // do proper checks
|
||||||
|
it.img = cast(size_t)cast(void*)img;
|
||||||
|
it.next = imglist;
|
||||||
|
imglist = it;
|
||||||
|
version(sdpy_debug_xshm) { import core.stdc.stdio : printf; printf("registering image %p\n", cast(void*)img); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unregisterImage (Image img) {
|
||||||
|
if (!imglistLocked && img !is null) {
|
||||||
|
import core.stdc.stdlib : free;
|
||||||
|
ImgList* prev = null;
|
||||||
|
ImgList* cur = imglist;
|
||||||
|
while (cur !is null) {
|
||||||
|
if (cur.img == cast(size_t)cast(void*)img) break; // i found her!
|
||||||
|
prev = cur;
|
||||||
|
cur = cur.next;
|
||||||
|
}
|
||||||
|
if (cur !is null) {
|
||||||
|
if (prev is null) imglist = cur.next; else prev.next = cur.next;
|
||||||
|
free(cur);
|
||||||
|
version(sdpy_debug_xshm) { import core.stdc.stdio : printf; printf("unregistering image %p\n", cast(void*)img); }
|
||||||
|
} else {
|
||||||
|
version(sdpy_debug_xshm) { import core.stdc.stdio : printf; printf("trying to unregister unknown image %p\n", cast(void*)img); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeImages () {
|
||||||
|
imglistLocked = true;
|
||||||
|
scope(exit) imglistLocked = false;
|
||||||
|
ImgList* cur = imglist;
|
||||||
|
ImgList* next = null;
|
||||||
|
while (cur !is null) {
|
||||||
|
import core.stdc.stdlib : free;
|
||||||
|
next = cur.next;
|
||||||
|
version(sdpy_debug_xshm) { import core.stdc.stdio : printf; printf("disposing image %p\n", cast(void*)cur.img); }
|
||||||
|
(cast(Image)cast(void*)cur.img).dispose();
|
||||||
|
free(cur);
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
imglist = null;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
static Display* get() {
|
static Display* get() {
|
||||||
if(display is null) {
|
if(display is null) {
|
||||||
|
@ -4512,6 +4570,9 @@ version(X11) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// close connection on program exit -- we need this to properly free all images
|
||||||
|
shared static ~this () { close(); }
|
||||||
|
|
||||||
///
|
///
|
||||||
static void close() {
|
static void close() {
|
||||||
if(display is null)
|
if(display is null)
|
||||||
|
@ -4522,6 +4583,9 @@ version(X11) {
|
||||||
removeFileEventListeners(display.fd);
|
removeFileEventListeners(display.fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now remove all registered images to prevent shared memory leaks
|
||||||
|
freeImages();
|
||||||
|
|
||||||
XCloseDisplay(display);
|
XCloseDisplay(display);
|
||||||
display = null;
|
display = null;
|
||||||
}
|
}
|
||||||
|
@ -4574,7 +4638,7 @@ version(X11) {
|
||||||
assert(rawData != cast(ubyte*) -1);
|
assert(rawData != cast(ubyte*) -1);
|
||||||
shminfo.readOnly = 0;
|
shminfo.readOnly = 0;
|
||||||
XShmAttach(display, &shminfo);
|
XShmAttach(display, &shminfo);
|
||||||
|
XDisplayConnection.registerImage(this);
|
||||||
} else {
|
} else {
|
||||||
// This actually needs to be malloc to avoid a double free error when XDestroyImage is called
|
// This actually needs to be malloc to avoid a double free error when XDestroyImage is called
|
||||||
import core.stdc.stdlib : malloc;
|
import core.stdc.stdlib : malloc;
|
||||||
|
@ -4595,8 +4659,10 @@ version(X11) {
|
||||||
void dispose() {
|
void dispose() {
|
||||||
// note: this calls free(rawData) for us
|
// note: this calls free(rawData) for us
|
||||||
if(handle) {
|
if(handle) {
|
||||||
if(usingXshm)
|
if (usingXshm) {
|
||||||
XShmDetach(XDisplayConnection.get(), &shminfo);
|
XDisplayConnection.unregisterImage(this);
|
||||||
|
if (XDisplayConnection.get()) XShmDetach(XDisplayConnection.get(), &shminfo);
|
||||||
|
}
|
||||||
XDestroyImage(handle);
|
XDestroyImage(handle);
|
||||||
if(usingXshm) {
|
if(usingXshm) {
|
||||||
shmdt(shminfo.shmaddr);
|
shmdt(shminfo.shmaddr);
|
||||||
|
|
Loading…
Reference in New Issue