LibIPC: Handle ECONNRESET when reading from the IPC socket

Reading from a socket with a dead peer returns the `ECONNRESET` error
code in some cases on Linux. This commit changes LibIPC to gracefully
shut down the socket if that happens, fixing an occasional crash in
Ladybird.

Fixes SerenityOS/ladybird#116
This commit is contained in:
Daniel Bertalan 2022-11-24 08:03:11 +01:00 committed by Andreas Kling
parent 45108438ce
commit efaf9f137a
Notes: sideshowbarker 2024-07-17 04:10:24 +09:00

View file

@ -157,6 +157,15 @@ ErrorOr<Vector<u8>> ConnectionBase::read_as_much_as_possible_from_socket_without
}
u8 buffer[4096];
bool should_shut_down = false;
auto schedule_shutdown = [this, &should_shut_down]() {
should_shut_down = true;
m_deferred_invoker->schedule([strong_this = NonnullRefPtr(*this)] {
strong_this->shutdown();
});
};
while (m_socket->is_open()) {
auto maybe_bytes_read = m_socket->read_without_waiting({ buffer, 4096 });
if (maybe_bytes_read.is_error()) {
@ -165,6 +174,11 @@ ErrorOr<Vector<u8>> ConnectionBase::read_as_much_as_possible_from_socket_without
break;
}
if (error.is_syscall() && error.code() == ECONNRESET) {
schedule_shutdown();
break;
}
dbgln("ConnectionBase::read_as_much_as_possible_from_socket_without_blocking: {}", error);
warnln("ConnectionBase::read_as_much_as_possible_from_socket_without_blocking: {}", error);
VERIFY_NOT_REACHED();
@ -172,12 +186,8 @@ ErrorOr<Vector<u8>> ConnectionBase::read_as_much_as_possible_from_socket_without
auto bytes_read = maybe_bytes_read.release_value();
if (bytes_read.is_empty()) {
m_deferred_invoker->schedule([strong_this = NonnullRefPtr(*this)] {
strong_this->shutdown();
});
if (!bytes.is_empty())
break;
return Error::from_string_literal("IPC connection EOF");
schedule_shutdown();
break;
}
bytes.append(bytes_read.data(), bytes_read.size());
@ -186,6 +196,8 @@ ErrorOr<Vector<u8>> ConnectionBase::read_as_much_as_possible_from_socket_without
if (!bytes.is_empty()) {
m_responsiveness_timer->stop();
did_become_responsive();
} else if (should_shut_down) {
return Error::from_string_literal("IPC connection EOF");
}
return bytes;