Cleanup objects created by extensions

This commit is contained in:
Oskari Alaranta 2026-02-21 03:47:29 +02:00
parent a32d509cde
commit d0b289d77b
3 changed files with 62 additions and 34 deletions

View File

@ -41,6 +41,7 @@ struct Object
Window, Window,
Pixmap, Pixmap,
GraphicsContext, GraphicsContext,
Extension,
}; };
Type type; Type type;
@ -133,7 +134,15 @@ struct Object
} }
}; };
BAN::Variant<Cursor, Window, Pixmap, GraphicsContext> object; struct Extension
{
uint8_t type_major;
uint8_t type_minor;
void* c_private;
void (*destructor)(Extension&);
};
BAN::Variant<Cursor, Window, Pixmap, GraphicsContext, Extension> object;
}; };
struct Client struct Client

View File

@ -11,15 +11,9 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
struct ShmSegment
{
void* addr;
};
static BAN::HashMap<CARD32, ShmSegment> s_shm_segments;
static BYTE s_shm_event_base; static BYTE s_shm_event_base;
static BYTE s_shm_error_base; static BYTE s_shm_error_base;
static BYTE s_shm_major_opcode;
static bool is_local_socket(int socket) static bool is_local_socket(int socket)
{ {
@ -60,6 +54,29 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
const uint8_t major_opcode = packet[0]; const uint8_t major_opcode = packet[0];
const uint8_t minor_opcode = packet[1]; const uint8_t minor_opcode = packet[1];
const auto get_shmseg =
[&client_info, minor_opcode, major_opcode](CARD32 shmseg) -> BAN::ErrorOr<void*>
{
auto it = g_objects.find(shmseg);
if (it != g_objects.end() && it->value->type == Object::Type::Extension)
{
auto& ext = it->value->object.get<Object::Extension>();
if (ext.type_major == s_shm_major_opcode && ext.type_minor == BadShmSeg)
return ext.c_private;
}
xError error {
.type = X_Error,
.errorCode = static_cast<BYTE>(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 = const auto get_drawable =
[&client_info, minor_opcode, major_opcode](WINDOW drawable) -> BAN::ErrorOr<Object&> [&client_info, minor_opcode, major_opcode](WINDOW drawable) -> BAN::ErrorOr<Object&>
{ {
@ -151,9 +168,19 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
void* addr = shmat(request.shmid, nullptr, request.readOnly ? SHM_RDONLY : 0); void* addr = shmat(request.shmid, nullptr, request.readOnly ? SHM_RDONLY : 0);
ASSERT(addr != (void*)-1); ASSERT(addr != (void*)-1);
TRY(s_shm_segments.insert(request.shmseg, { TRY(client_info.objects.insert(request.shmseg));
.addr = addr, TRY(g_objects.insert(
})); request.shmseg,
TRY(BAN::UniqPtr<Object>::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 { xShmCompletionEvent event {
.type = static_cast<BYTE>(s_shm_event_base + ShmCompletion), .type = static_cast<BYTE>(s_shm_event_base + ShmCompletion),
@ -173,24 +200,11 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
dprintln("ShmDetach"); dprintln("ShmDetach");
dprintln(" shmseg: {}", request.shmseg); dprintln(" shmseg: {}", request.shmseg);
auto it = s_shm_segments.find(request.shmseg); void* shm_segment = TRY(get_shmseg(request.shmseg));
if (it != s_shm_segments.end()) shmdt(shm_segment);
{
shmdt(it->value.addr); client_info.objects.remove(request.shmseg);
s_shm_segments.remove(it); g_objects.remove(request.shmseg);
}
else
{
xError error {
.type = X_Error,
.errorCode = static_cast<BYTE>(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));
}
break; break;
} }
@ -217,7 +231,7 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
dprintln(" offset: {}", request.offset); dprintln(" offset: {}", request.offset);
#endif #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& object = TRY_REF(get_drawable(request.drawable));
auto [out_data, out_w, out_h, out_depth] = get_drawable_info(object); auto [out_data, out_w, out_h, out_depth] = get_drawable_info(object);
@ -233,7 +247,7 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
.out_w = out_w, .out_w = out_w,
.out_h = out_h, .out_h = out_h,
.out_depth = out_depth, .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_x = request.srcX,
.in_y = request.srcY, .in_y = request.srcY,
.in_w = request.totalWidth, .in_w = request.totalWidth,
@ -278,7 +292,7 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
dprintln(" shmseg: {}", request.shmseg); dprintln(" shmseg: {}", request.shmseg);
dprintln(" offset: {}", request.offset); 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& object = TRY_REF(get_drawable(request.drawable));
auto [in_data, in_w, in_h, in_depth] = get_drawable_info(object); auto [in_data, in_w, in_h, in_depth] = get_drawable_info(object);
@ -286,7 +300,7 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
const auto dwords = image_dwords(request.width, request.height, in_depth); const auto dwords = image_dwords(request.width, request.height, in_depth);
get_image({ 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_data = in_data.data(),
.in_x = request.x, .in_x = request.x,
.in_y = request.y, .in_y = request.y,
@ -363,6 +377,7 @@ static struct SHMInstaller
continue; continue;
s_shm_event_base = extension.event_base; s_shm_event_base = extension.event_base;
s_shm_error_base = extension.error_base; s_shm_error_base = extension.error_base;
s_shm_major_opcode = extension.major_opcode;
break; break;
} }
} }

View File

@ -1,7 +1,6 @@
#include "Base.h" #include "Base.h"
#include "Definitions.h" #include "Definitions.h"
#include "Keymap.h" #include "Keymap.h"
#include "Utils.h"
#include <X11/X.h> #include <X11/X.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
@ -268,6 +267,11 @@ int main()
g_epoll_thingies.remove(gui_window->server_fd()); g_epoll_thingies.remove(gui_window->server_fd());
} }
} }
if (object.type == Object::Type::Extension)
{
auto& extension = object.object.get<Object::Extension>();
extension.destructor(extension);
}
g_objects.remove(it); g_objects.remove(it);
} }