diff options
| author | Maxime Coste <mawww@kakoune.org> | 2022-05-10 22:33:52 +1000 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2022-05-10 22:36:13 +1000 |
| commit | ae001a1f911181ec0ca752212e5ebaf5f57c4ad0 (patch) | |
| tree | a26ccc953277ddb2e14545b1b6b7e57dc6fc1e59 /src | |
| parent | 3882b0e21b7ff8d7a6ad9e8fb9961eaa104d1b18 (diff) | |
Run EventManager whenever writing to a file descriptor would block
This approach is not very elegant as it hooks into the event manager
deep inside the call graph, but solves the exiting issue and is an
okay stop gap solution until a better design comes up.
Fixes #4605
Diffstat (limited to 'src')
| -rw-r--r-- | src/file.cc | 18 |
1 files changed, 13 insertions, 5 deletions
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)); } } |
