Skip to content

Commit 169e19a

Browse files
committed
PROTON-2930: epoll proator repeated epoll_wait on disconnected socket
1 parent 0643d7c commit 169e19a

1 file changed

Lines changed: 17 additions & 1 deletion

File tree

c/src/proactor/epoll.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,12 +980,28 @@ static inline bool pconnection_wclosed(pconnection_t *pc) {
980980
Never rearm(0 | EPOLLONESHOT), since this really means
981981
rearm(EPOLLHUP | EPOLLERR | EPOLLONESHOT) and leaves doubt that the
982982
EPOLL_CTL_DEL can prevent a parallel HUP/ERR error notification during
983-
close/shutdown. Let read()/write() return 0 or -1 to trigger cleanup logic.
983+
close/shutdown.
984+
985+
Normally, let send()/recv() return 0 or -1 to trigger cleanup logic.
984986
*/
985987
static int pconnection_rearm_check(pconnection_t *pc) {
986988
if ((pconnection_rclosed(pc) && pconnection_wclosed(pc)) || pc->psocket.epoll_io.fd == -1) {
987989
return 0;
990+
} else if (pc->disconnected) {
991+
// Transport not closed, yet IO not possible. Skip another epoll since it will return
992+
// immediately. PROTON-2930: either send/recv not called or no error (i.e. EAGAIN).
993+
int soerr;
994+
socklen_t soerrlen = sizeof(soerr);
995+
int ec = getsockopt(pc->psocket.epoll_io.fd, SOL_SOCKET, SO_ERROR, &soerr, &soerrlen);
996+
if (ec || !soerr) {
997+
soerr = ENOTCONN;
998+
}
999+
// Force transport closure.
1000+
psocket_error(&pc->psocket, soerr, pc->connected ? "disconnected" : "on connect");
1001+
schedule(&pc->task); // unassign_thread handles notify_poller requirement.
1002+
return 0;
9881003
}
1004+
9891005
uint32_t wanted_now = (pc->read_blocked && !pconnection_rclosed(pc)) ? EPOLLIN : 0;
9901006
if (!pconnection_wclosed(pc)) {
9911007
if (pc->write_blocked)

0 commit comments

Comments
 (0)