tcp_io: fix error_cb busy-spin on graceful EPOLLHUP; socks_proxy: close local socket on both FINs
- error_cb (tcp_io): при graceful HUP (SO_ERROR==0) после уже прочитанного FIN сокет оставался в epoll и level-triggered EPOLLHUP крутил цикл на 100% CPU. Теперь сокет закрывается через tcp_conn_push_close. - socks_proxy on_fin_cb: при обоих обменянных FIN локальный сокет закрывается (send_close + push_close), симметрично exit-стороне (tcp_proxy_server).
This commit is contained in:
1 parent
56d0928632
commit
ce12f058d9
3 files changed
+23
-2
No files matched your search
+9
-1
@@ -417,7 +417,15 @@ static void error_cb(socket_t sock, void* arg) {
|
||||
if (!tc || tc->sock == SOCKET_INVALID) return;
|
||||
int so_err = 0; socklen_t so_len = sizeof(so_err);
|
||||
if (getsockopt(tc->sock, SOL_SOCKET, SO_ERROR, &so_err, &so_len) == 0 && so_err == 0) {
|
||||
if (tc->fin_remote) return;
|
||||
// Peer полностью закрыл свой сокет (EPOLLHUP) после того, как FIN уже прочитан (fin_remote=1).
|
||||
// EPOLLHUP — level-triggered и «always reported»: если оставить сокет в epoll, каждая итерация
|
||||
// epoll_wait мгновенно вернёт HUP и error_cb зациклится на 100% CPU. Закрываем сокет.
|
||||
if (tc->fin_remote) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "tcp_io: async HUP (graceful) fd=%d — peer fully closed after FIN, closing",
|
||||
(int)tc->sock);
|
||||
tcp_conn_push_close(tc);
|
||||
return;
|
||||
}
|
||||
// Грациозное закрытие peer (FIN, EPOLLHUP) при приостановленном чтении: FIN пришёл не как
|
||||
// EPOLLIN (чтение отключено backpressure-ом), а как HUP. Возобновляем чтение, чтобы
|
||||
// read_cb дослил остаток и прочитал FIN (recv()==0 → fin_remote → отложенный on_fin).
|
||||
|
||||
Reference in new issue
Block a user