Skip to content

Commit

Permalink
context: Make buffer thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
wismill committed Nov 25, 2024
1 parent 6153fec commit ec44f84
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 11 deletions.
46 changes: 41 additions & 5 deletions src/context-priv.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <sys/types.h>
#include <sys/stat.h>
#include <threads.h>
#include <errno.h>

#include "xkbcommon/xkbcommon.h"
Expand Down Expand Up @@ -92,19 +93,54 @@ xkb_log(struct xkb_context *ctx, enum xkb_log_level level, int verbosity,
va_end(args);
}

bool
xkb_context_create_buffer(struct xkb_context *ctx)
{
if (tss_get(ctx->text_buffer))
return true;
if (tss_create(&ctx->text_buffer, NULL) == thrd_error)
goto create_error;
context_buffer *buf = calloc(1, sizeof(context_buffer));
if (!buf)
goto alloc_error;
if (tss_set(ctx->text_buffer, buf) == thrd_error)
goto set_error;
return true;

set_error:
free(buf);
alloc_error:
tss_delete(ctx->text_buffer);
create_error:
log_err(ctx, XKB_ERROR_ALLOCATION_ERROR,
"Cannot create context buffer\n");
return false;
}

void
xkb_context_destroy_buffer(struct xkb_context *ctx)
{
context_buffer *buf = tss_get(ctx->text_buffer);
if (!buf)
return;
free(buf);
tss_delete(ctx->text_buffer);
}

char *
xkb_context_get_buffer(struct xkb_context *ctx, size_t size)
{
char *rtrn;
context_buffer *buf = tss_get(ctx->text_buffer);

if (size >= sizeof(ctx->text_buffer))
if (!buf || size >= ARRAY_SIZE(buf->text))
return NULL;

if (sizeof(ctx->text_buffer) - ctx->text_next <= size)
ctx->text_next = 0;
if (ARRAY_SIZE(buf->text) - buf->next <= size)
buf->next = 0;

rtrn = &ctx->text_buffer[ctx->text_next];
ctx->text_next += size;
rtrn = &buf->text[buf->next];
buf->next += size;

return rtrn;
}
Expand Down
16 changes: 14 additions & 2 deletions src/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,16 @@
#ifndef CONTEXT_H
#define CONTEXT_H

#include <threads.h>

#include "atom.h"
#include "messages-codes.h"

typedef struct {
char text[2048];
size_t next;
} context_buffer;

struct xkb_context {
int refcnt;

Expand All @@ -50,8 +57,7 @@ struct xkb_context {
void *x11_atom_cache;

/* Buffer for the *Text() functions. */
char text_buffer[2048];
size_t text_next;
tss_t text_buffer;

unsigned int use_environment_names : 1;
unsigned int use_secure_getenv : 1;
Expand Down Expand Up @@ -98,6 +104,12 @@ xkb_atom_steal(struct xkb_context *ctx, char *string);
const char *
xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom);

bool
xkb_context_create_buffer(struct xkb_context *ctx);

void
xkb_context_destroy_buffer(struct xkb_context *ctx);

char *
xkb_context_get_buffer(struct xkb_context *ctx, size_t size);

Expand Down
6 changes: 5 additions & 1 deletion src/xkbcomp/keymap-dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,10 +733,14 @@ text_v1_keymap_get_as_string(struct xkb_keymap *keymap)
{
struct buf buf = { NULL, 0, 0 };

if (!xkb_context_create_buffer(keymap->ctx))
return false;

if (!write_keymap(keymap, &buf)) {
free(buf.buf);
return NULL;
buf.buf = NULL;
}

xkb_context_destroy_buffer(keymap->ctx);
return buf.buf;
}
24 changes: 21 additions & 3 deletions src/xkbcomp/xkbcomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ text_v1_keymap_new_from_names(struct xkb_keymap *keymap,
"compat '%s', symbols '%s'\n",
kccgst.keycodes, kccgst.types, kccgst.compat, kccgst.symbols);

if (!xkb_context_create_buffer(keymap->ctx))
return false;

file = XkbFileFromComponents(keymap->ctx, &kccgst);

free(kccgst.keycodes);
Expand All @@ -93,11 +96,14 @@ text_v1_keymap_new_from_names(struct xkb_keymap *keymap,
if (!file) {
log_err(keymap->ctx, XKB_ERROR_KEYMAP_COMPILATION_FAILED,
"Failed to generate parsed XKB file from components\n");
return false;
ok = false;
goto xkb_file_error;
}

ok = compile_keymap_file(keymap, file);
FreeXkbFile(file);
xkb_file_error:
xkb_context_destroy_buffer(keymap->ctx);
return ok;
}

Expand All @@ -108,15 +114,21 @@ text_v1_keymap_new_from_string(struct xkb_keymap *keymap,
bool ok;
XkbFile *xkb_file;

if (!xkb_context_create_buffer(keymap->ctx))
return false;

xkb_file = XkbParseString(keymap->ctx, string, len, "(input string)", NULL);
if (!xkb_file) {
log_err(keymap->ctx, XKB_ERROR_KEYMAP_COMPILATION_FAILED,
"Failed to parse input xkb string\n");
return false;
ok = false;
goto xkb_file_error;
}

ok = compile_keymap_file(keymap, xkb_file);
FreeXkbFile(xkb_file);
xkb_file_error:
xkb_context_destroy_buffer(keymap->ctx);
return ok;
}

Expand All @@ -126,15 +138,21 @@ text_v1_keymap_new_from_file(struct xkb_keymap *keymap, FILE *file)
bool ok;
XkbFile *xkb_file;

if (!xkb_context_create_buffer(keymap->ctx))
return false;

xkb_file = XkbParseFile(keymap->ctx, file, "(unknown file)", NULL);
if (!xkb_file) {
log_err(keymap->ctx, XKB_ERROR_KEYMAP_COMPILATION_FAILED,
"Failed to parse input xkb file\n");
return false;
ok = false;
goto xkb_file_error;
}

ok = compile_keymap_file(keymap, xkb_file);
FreeXkbFile(xkb_file);
xkb_file_error:
xkb_context_destroy_buffer(keymap->ctx);
return ok;
}

Expand Down

0 comments on commit ec44f84

Please sign in to comment.