ltk

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

commit 77c8746b41398dffda734c31e1697d2aaba752d4
parent 9de2d4ac1734343f1de02c9ec29e408ccc05689c
Author: lumidify <nobody@lumidify.org>
Date:   Tue, 26 Mar 2024 10:51:16 +0100

Possibly fix nondeterministic freezing in ltkd

Pango performs some initialization in a separate thread, causing
issues when ltkd daemonizes itself. The previous hack was to create
a text line before daemonization so the Pango initialization has to
finish first, but that still didn't always work. Now, Pango is only
initialized after daemonization. That seems to be working well so far,
but I don't know if there are still some edge cases.

Diffstat:
Msrc/ltk/text_pango.c | 20+++++++++++++++++---
Msrc/ltkd/ltkd.c | 15+--------------
2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/src/ltk/text_pango.c b/src/ltk/text_pango.c @@ -54,18 +54,31 @@ ltk_text_context * ltk_text_context_create(ltk_renderdata *data, char *default_font) { ltk_text_context *ctx = ltk_malloc(sizeof(ltk_text_context)); ctx->data = data; - ctx->fontmap = pango_xft_get_font_map(data->dpy, data->screen); - ctx->context = pango_font_map_create_context(ctx->fontmap); + ctx->fontmap = NULL; + ctx->context = NULL; ctx->default_font = ltk_strdup(default_font); return ctx; } +/* NOTE: It is crucial that the text context is initialized lazily instead of + directly in the beginning. Pango does some initialization work in a separate + thread, which causes problems when ltkd daemonizes itself, so the Pango + initialization is only allowed to take place after daemonization. */ +static void +ltk_text_context_init(ltk_text_context *ctx) { + if (!ctx->fontmap) { + ctx->fontmap = pango_xft_get_font_map(ctx->data->dpy, ctx->data->screen); + ctx->context = pango_font_map_create_context(ctx->fontmap); + } +} + void ltk_text_context_destroy(ltk_text_context *ctx) { ltk_free(ctx->default_font); /* FIXME: if both are unref'd, there is a segfault - what is the normal thing to do here? */ - g_object_unref(ctx->fontmap); + if (ctx->fontmap) + g_object_unref(ctx->fontmap); /*g_object_unref(ctx->context);*/ ltk_free(ctx); } @@ -92,6 +105,7 @@ ltk_text_line_set_text(ltk_text_line *tl, char *text, int take_over_text) { ltk_text_line * ltk_text_line_create(ltk_text_context *ctx, uint16_t font_size, char *text, int take_over_text, int width) { + ltk_text_context_init(ctx); ltk_text_line *tl = ltk_malloc(sizeof(ltk_text_line)); if (take_over_text) tl->text = text; diff --git a/src/ltkd/ltkd.c b/src/ltkd/ltkd.c @@ -204,20 +204,6 @@ main(int argc, char *argv[]) { main_window = ltk_window_create(title, 0, 0, 500, 500); ltk_widget_register_signal_handler(LTK_CAST_WIDGET(main_window), LTK_WINDOW_SIGNAL_CLOSE, &ltkd_window_close, LTK_ARG_VOID); - /* This hack is necessary to make the daemonization work properly when using Pango. - This may not be entirely accurate, but from what I gather, newer versions of Pango - initialize Fontconfig in a separate thread to avoid startup overhead. This leads - to non-deterministic behavior because the Fontconfig initialization doesn't work - properly after daemonization. Creating a text line and getting the size waits until - Fontconfig is initialized. Getting the size is important because Pango doesn't - actually do much until you try to use the line for something. */ - /* FIXME: I guess just calling FcInit manually in the text backend could work as well. */ - /* FIXME: Maybe just call this when actually daemonizing. */ - ltk_text_line *tmp = ltk_text_line_create_default(10, "hi", 0, -1); - int tw, th; - ltk_text_line_get_size(tmp, &tw, &th); - ltk_text_line_destroy(tmp); - sock_path = get_sock_path(ltkd_dir, ltk_renderer_get_window_id(main_window->renderwindow)); if (!sock_path) ltkd_fatal_errno("Unable to allocate memory for socket path.\n"); @@ -437,6 +423,7 @@ daemonize(void) { else if (pid != 0) exit(0); + /* FIXME: does this cause any issues with the lazy initialization of pango/fontconfig? */ if (chdir("/") < 0) ltkd_fatal_errno("Can't change directory to root.\n");