From ad25b64faba075de4df1ff4c74fd1475e29e5683 Mon Sep 17 00:00:00 2001 From: jake champion Date: Fri, 27 Feb 2026 10:55:40 +0000 Subject: [PATCH] fix cancel/accept race in NetAccept that causes EBADF abort `NetAcceptAction::cancel()` closes the server socket before setting the cancelled flag In the window between close and flag set, `net_accept()` can get `EBADF` from `accept4()`, see `cancelled=false`, and dispatch `EVENT_ERROR` to handlers that don't expect it now we check the atomic server pointer in all three accept paths before dispatching `EVENT_ERROR` --- src/iocore/net/UnixNetAccept.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/iocore/net/UnixNetAccept.cc b/src/iocore/net/UnixNetAccept.cc index 66e73096fa2..0e72a681c7c 100644 --- a/src/iocore/net/UnixNetAccept.cc +++ b/src/iocore/net/UnixNetAccept.cc @@ -112,7 +112,7 @@ net_accept(NetAccept *na, void *ep, bool blockable) if (res == -EAGAIN || res == -ECONNABORTED || res == -EPIPE) { goto Ldone; } - if (na->server.sock.is_ok() && !na->action_->cancelled) { + if (na->action_->server.load(std::memory_order_acquire) != nullptr && na->server.sock.is_ok() && !na->action_->cancelled) { if (!blockable) { na->action_->continuation->handleEvent(EVENT_ERROR, reinterpret_cast(res)); } else { @@ -387,7 +387,7 @@ NetAccept::do_blocking_accept(EThread *t) case -1: [[fallthrough]]; default: - if (!action_->cancelled) { + if (action_->server.load(std::memory_order_acquire) != nullptr && !action_->cancelled) { SCOPED_MUTEX_LOCK(lock, action_->mutex ? action_->mutex : t->mutex, t); action_->continuation->handleEvent(EVENT_ERROR, reinterpret_cast(res)); Warning("accept thread received fatal error: errno = %d", errno); @@ -580,7 +580,7 @@ NetAccept::acceptFastEvent(int event, void *ep) check_transient_accept_error(res); goto Ldone; } - if (!action_->cancelled) { + if (action_->server.load(std::memory_order_acquire) != nullptr && !action_->cancelled) { action_->continuation->handleEvent(EVENT_ERROR, reinterpret_cast(res)); } goto Lerror;