From 90edc096971aa013dbacf1315271c2f2da62bd59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 23 Nov 2020 19:26:00 +0100 Subject: [PATCH] =?UTF-8?q?render:=20don=E2=80=99t=20call=20term=5Farm=5Fb?= =?UTF-8?q?link=5Ftimer()=20from=20multiple=20threads?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We call term_arm_blink_timer() from render_cell(), which runs in multiple threads. This caused multiple blink timer FDs to be created and registered with the FDM, later causing read failures after one of those FDs had been closed again. This rarely happened under normal circumstances, but was easy to trigger when the whole screen was full of blinking text. As a small optimization, we don’t bother taking the lock if the timer FD already is valid. This is safe, because: 1) If the timer FD isn’t valid, we take the lock and then call term_arm_blink_timer(), which again checks if the FD is already valid. 2) The blink timer FD cannot be closed while we’re rendering cells. It is only disabled in the FDM callback, which cannot execute while we’re rendering. --- render.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/render.c b/render.c index 9a3fef0f..b4afab83 100644 --- a/render.c +++ b/render.c @@ -487,8 +487,12 @@ render_cell(struct terminal *term, pixman_image_t *pix, PIXMAN_OP_SRC, pix, &bg, 1, &(pixman_rectangle16_t){x, y, cell_cols * width, height}); - if (cell->attrs.blink) + if (cell->attrs.blink && term->blink.fd < 0) { + /* TODO: use a custom lock for this? */ + mtx_lock(&term->render.workers.lock); term_arm_blink_timer(term); + mtx_unlock(&term->render.workers.lock); + } if (has_cursor && term->cursor_style == CURSOR_BLOCK && term->kbd_focus) draw_cursor(term, cell, font, pix, &fg, &bg, x, y, cell_cols); @@ -499,7 +503,6 @@ render_cell(struct terminal *term, pixman_image_t *pix, pixman_image_t *clr_pix = pixman_image_create_solid_fill(&fg); if (glyph != NULL) { - /* Clip to cell */ if (unlikely(pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8)) { /* Glyph surface is a pre-rendered image (typically a color emoji...) */ if (!(cell->attrs.blink && term->blink.state == BLINK_OFF)) {