From 70d72b22d89e926e41ba587e4976db53dad21248 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 13 Oct 2024 09:49:44 +0530 Subject: [PATCH] Graphics protocol: Clear any partially uploaded data for a chunked load when any delete command is received Fixes #7968 --- docs/graphics-protocol.rst | 3 +++ kitty/graphics.c | 1 + kitty_tests/graphics.py | 11 +++++++++++ 3 files changed, 15 insertions(+) diff --git a/docs/graphics-protocol.rst b/docs/graphics-protocol.rst index f05c2869f..a13bf04c9 100644 --- a/docs/graphics-protocol.rst +++ b/docs/graphics-protocol.rst @@ -754,6 +754,9 @@ deleted, if the capital letter form above is specified. Also, when the terminal is running out of quota space for new images, existing images without placements will be preferentially deleted. +If an image is being loaded in chunks and the upload is not complete when any +delete command is received, the partial upload must be aborted. + Some examples:: _Ga=d\ # delete all visible placements diff --git a/kitty/graphics.c b/kitty/graphics.c index b1715603d..57e53fb59 100644 --- a/kitty/graphics.c +++ b/kitty/graphics.c @@ -2096,6 +2096,7 @@ point3d_filter_func(const ImageRef *ref, Image *img, const void *data, CellPixel static void handle_delete_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c, bool *is_dirty, CellPixelSize cell) { + if (self->currently_loading.loading_for.image_id) free_load_data(&self->currently_loading); GraphicsCommand d; bool only_first_image = false; switch (g->delete_action) { diff --git a/kitty_tests/graphics.py b/kitty_tests/graphics.py index 266c72d08..9ad79d64f 100644 --- a/kitty_tests/graphics.py +++ b/kitty_tests/graphics.py @@ -410,6 +410,17 @@ class TestGraphics(BaseTest): img = g.image_for_client_id(1) self.ae(img['data'], b'abcdefghijklmnop') + # Test interrupted and retried chunked load + self.assertIsNone(pl('abcd', s=2, v=2, m=1)) + self.assertIsNone(pl('efgh', m=1)) + send_command(s, 'a=d') # delete command should clear partial transfer + self.assertIsNone(pl('abcd', s=2, v=2, m=1)) + self.assertIsNone(pl('efgh', m=1)) + self.assertIsNone(pl('ijkl', m=1)) + self.ae(pl('1234', m=0), 'OK') + img = g.image_for_client_id(1) + self.ae(img['data'], b'abcdefghijkl1234') + random_data = byte_block(32 * 1024) sl( random_data,