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,
Pixmap,
GraphicsContext,
Extension,
};
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

View File

@ -11,15 +11,9 @@
#include <sys/socket.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_error_base;
static BYTE s_shm_major_opcode;
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 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 =
[&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);
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<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 {
.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(" 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<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));
}
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<void> 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<void> 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<void> 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<void> 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;
}
}

View File

@ -1,7 +1,6 @@
#include "Base.h"
#include "Definitions.h"
#include "Keymap.h"
#include "Utils.h"
#include <X11/X.h>
#include <X11/Xatom.h>
@ -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<Object::Extension>();
extension.destructor(extension);
}
g_objects.remove(it);
}