From d0b289d77b5e26238a2468a313d9d63093e39840 Mon Sep 17 00:00:00 2001 From: Oskari Alaranta Date: Sat, 21 Feb 2026 03:47:29 +0200 Subject: [PATCH] Cleanup objects created by extensions --- xbanan/Definitions.h | 11 +++++- xbanan/ExtSHM.cpp | 79 ++++++++++++++++++++++++++------------------ xbanan/main.cpp | 6 +++- 3 files changed, 62 insertions(+), 34 deletions(-) diff --git a/xbanan/Definitions.h b/xbanan/Definitions.h index 0f9b07c..64523a1 100644 --- a/xbanan/Definitions.h +++ b/xbanan/Definitions.h @@ -41,6 +41,7 @@ struct Object Window, Pixmap, GraphicsContext, + Extension, }; Type type; @@ -133,7 +134,15 @@ struct Object } }; - BAN::Variant object; + struct Extension + { + uint8_t type_major; + uint8_t type_minor; + void* c_private; + void (*destructor)(Extension&); + }; + + BAN::Variant object; }; struct Client diff --git a/xbanan/ExtSHM.cpp b/xbanan/ExtSHM.cpp index b13282c..85e0064 100644 --- a/xbanan/ExtSHM.cpp +++ b/xbanan/ExtSHM.cpp @@ -11,15 +11,9 @@ #include #include -struct ShmSegment -{ - void* addr; -}; - -static BAN::HashMap s_shm_segments; - static BYTE s_shm_event_base; static BYTE s_shm_error_base; +static BYTE s_shm_major_opcode; static bool is_local_socket(int socket) { @@ -60,6 +54,29 @@ static BAN::ErrorOr extension_shm(Client& client_info, BAN::ConstByteSpan const uint8_t major_opcode = packet[0]; const uint8_t minor_opcode = packet[1]; + const auto get_shmseg = + [&client_info, minor_opcode, major_opcode](CARD32 shmseg) -> BAN::ErrorOr + { + auto it = g_objects.find(shmseg); + if (it != g_objects.end() && it->value->type == Object::Type::Extension) + { + auto& ext = it->value->object.get(); + if (ext.type_major == s_shm_major_opcode && ext.type_minor == BadShmSeg) + return ext.c_private; + } + + xError error { + .type = X_Error, + .errorCode = static_cast(s_shm_error_base + BadShmSeg), + .sequenceNumber = client_info.sequence, + .resourceID = shmseg, + .minorCode = minor_opcode, + .majorCode = major_opcode, + }; + TRY(encode(client_info.output_buffer, error)); + return BAN::Error::from_errno(ENOENT); + }; + const auto get_drawable = [&client_info, minor_opcode, major_opcode](WINDOW drawable) -> BAN::ErrorOr { @@ -151,9 +168,19 @@ static BAN::ErrorOr extension_shm(Client& client_info, BAN::ConstByteSpan void* addr = shmat(request.shmid, nullptr, request.readOnly ? SHM_RDONLY : 0); ASSERT(addr != (void*)-1); - TRY(s_shm_segments.insert(request.shmseg, { - .addr = addr, - })); + TRY(client_info.objects.insert(request.shmseg)); + TRY(g_objects.insert( + request.shmseg, + TRY(BAN::UniqPtr::create(Object { + .type = Object::Type::Extension, + .object = Object::Extension { + .type_major = s_shm_major_opcode, + .type_minor = BadShmSeg, + .c_private = addr, + .destructor = [](auto& ext) { shmdt(ext.c_private); }, + }, + })) + )); xShmCompletionEvent event { .type = static_cast(s_shm_event_base + ShmCompletion), @@ -173,24 +200,11 @@ static BAN::ErrorOr extension_shm(Client& client_info, BAN::ConstByteSpan dprintln("ShmDetach"); dprintln(" shmseg: {}", request.shmseg); - auto it = s_shm_segments.find(request.shmseg); - if (it != s_shm_segments.end()) - { - shmdt(it->value.addr); - s_shm_segments.remove(it); - } - else - { - xError error { - .type = X_Error, - .errorCode = static_cast(s_shm_error_base + BadShmSeg), - .sequenceNumber = client_info.sequence, - .resourceID = request.shmseg, - .minorCode = minor_opcode, - .majorCode = major_opcode, - }; - TRY(encode(client_info.output_buffer, error)); - } + void* shm_segment = TRY(get_shmseg(request.shmseg)); + shmdt(shm_segment); + + client_info.objects.remove(request.shmseg); + g_objects.remove(request.shmseg); break; } @@ -217,7 +231,7 @@ static BAN::ErrorOr extension_shm(Client& client_info, BAN::ConstByteSpan dprintln(" offset: {}", request.offset); #endif - auto& shm_segment = s_shm_segments[request.shmseg]; + void* shm_segment = TRY(get_shmseg(request.shmseg)); auto& object = TRY_REF(get_drawable(request.drawable)); auto [out_data, out_w, out_h, out_depth] = get_drawable_info(object); @@ -233,7 +247,7 @@ static BAN::ErrorOr extension_shm(Client& client_info, BAN::ConstByteSpan .out_w = out_w, .out_h = out_h, .out_depth = out_depth, - .in_data = (const uint8_t*)shm_segment.addr + request.offset, + .in_data = (const uint8_t*)shm_segment + request.offset, .in_x = request.srcX, .in_y = request.srcY, .in_w = request.totalWidth, @@ -278,7 +292,7 @@ static BAN::ErrorOr extension_shm(Client& client_info, BAN::ConstByteSpan dprintln(" shmseg: {}", request.shmseg); dprintln(" offset: {}", request.offset); - auto& shm_segment = s_shm_segments[request.shmseg]; + void* shm_segment = TRY(get_shmseg(request.shmseg)); auto& object = TRY_REF(get_drawable(request.drawable)); auto [in_data, in_w, in_h, in_depth] = get_drawable_info(object); @@ -286,7 +300,7 @@ static BAN::ErrorOr extension_shm(Client& client_info, BAN::ConstByteSpan const auto dwords = image_dwords(request.width, request.height, in_depth); get_image({ - .out_data = (uint8_t*)shm_segment.addr + request.offset, + .out_data = (uint8_t*)shm_segment + request.offset, .in_data = in_data.data(), .in_x = request.x, .in_y = request.y, @@ -363,6 +377,7 @@ static struct SHMInstaller continue; s_shm_event_base = extension.event_base; s_shm_error_base = extension.error_base; + s_shm_major_opcode = extension.major_opcode; break; } } diff --git a/xbanan/main.cpp b/xbanan/main.cpp index ea75735..f686ddb 100644 --- a/xbanan/main.cpp +++ b/xbanan/main.cpp @@ -1,7 +1,6 @@ #include "Base.h" #include "Definitions.h" #include "Keymap.h" -#include "Utils.h" #include #include @@ -268,6 +267,11 @@ int main() g_epoll_thingies.remove(gui_window->server_fd()); } } + if (object.type == Object::Type::Extension) + { + auto& extension = object.object.get(); + extension.destructor(extension); + } g_objects.remove(it); }