diff --git a/src/file.cc b/src/file.cc index e5d330be..60210e35 100644 --- a/src/file.cc +++ b/src/file.cc @@ -5,6 +5,7 @@ #include "exception.hh" #include "flags.hh" #include "option_types.hh" +#include "event_manager.hh" #include "ranked_match.hh" #include "regex.hh" #include "string.hh" @@ -256,13 +257,20 @@ void write(int fd, StringView data) const char* ptr = data.data(); ssize_t count = (int)data.length(); + int flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + auto restore_flags = on_scope_end([&] { fcntl(fd, F_SETFL, flags); }); + while (count) { - ssize_t written = ::write(fd, ptr, count); - ptr += written; - count -= written; - - if (written == -1) + if (ssize_t written = ::write(fd, ptr, count); written != -1) + { + ptr += written; + count -= written; + } + else if (errno == EAGAIN and EventManager::has_instance()) + EventManager::instance().handle_next_events(EventMode::Urgent, nullptr, false); + else throw file_access_error(format("fd: {}", fd), strerror(errno)); } } diff --git a/test/regression/4605-fifo-hang/cmd b/test/regression/4605-fifo-hang/cmd new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/regression/4605-fifo-hang/cmd @@ -0,0 +1 @@ + diff --git a/test/regression/4605-fifo-hang/rc b/test/regression/4605-fifo-hang/rc new file mode 100644 index 00000000..8829ee78 --- /dev/null +++ b/test/regression/4605-fifo-hang/rc @@ -0,0 +1,5 @@ +exec 5000oabcdefghi%yppppp +nop %sh{ + echo "write $kak_response_fifo" > "$kak_command_fifo" + strace -o /tmp/strace.log cat "$kak_response_fifo" +}