diff --git a/docs/changelog.rst b/docs/changelog.rst index e6d7d95cb..b4151e658 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -217,6 +217,8 @@ Detailed list of changes - Password input in kittens: hide the cursor and display 🔒 (U+1F512) at the end of typed characters to make it visually clear the user is entering a password +- DnD: Use non-blocking I/O when reading file chunks in ``drop_send_file_chunks()`` to avoid blocking the main event loop + 0.46.2 [2026-03-21] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kitty/dnd.c b/kitty/dnd.c index 2b2d5fbd2..ea3e438ca 100644 --- a/kitty/dnd.c +++ b/kitty/dnd.c @@ -552,6 +552,11 @@ drop_send_file_chunks(Window *w) { ssize_t n; do { n = read(w->drop.file_fd_plus_one - 1, buf, sizeof(buf)); } while (n < 0 && errno == EINTR); if (n < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + /* No data available right now; retry via timer */ + w->drop.file_send_timer = add_main_loop_timer(ms_to_monotonic_t(20), false, file_send_timer_callback, (void*)(uintptr_t)w->id, NULL); + return; + } drop_close_file_fd(w); drop_send_error(w, EIO); return; @@ -583,7 +588,7 @@ drop_send_file_chunks(Window *w) { static void drop_send_file_data(Window *w, const char *path) { drop_close_file_fd(w); - int fd = safe_open(path, O_RDONLY | O_CLOEXEC, 0); + int fd = safe_open(path, O_RDONLY | O_CLOEXEC | O_NONBLOCK, 0); if (fd < 0) { switch (errno) { case ENOENT: case ENOTDIR: drop_send_error(w, ENOENT); break;