Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

context: Make buffer thread-safe #544

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading