libtorrent icon indicating copy to clipboard operation
libtorrent copied to clipboard

Listen queue overflow / incorrect accept() use

Open rozhuk-im opened this issue 8 months ago • 7 comments

Hi!

I am running 0.15.1 on FreeBSD 14/stable and got messages in logs:

Mar 29 00:45:52 firewall kernel: [9615729] sonewconn: pcb 0xfffff801ca667a80 ([::]:8443 (proto 6)): Listen queue overflow: 193 already in queue awaiting acceptance (1 occurrences), euid 80, rgid 80, jail 0
Mar 29 00:45:52 firewall kernel: [9615729] sonewconn: pcb 0xfffff801ca667a80 ([::]:8443 (proto 6)): Listen queue overflow: 193 already in queue awaiting acceptance (1 occurrences), euid 80, rgid 80, jail 0
Mar 29 00:46:53 firewall kernel: [9615790] sonewconn: pcb 0xfffff801ca667a80 ([::]:8443 (proto 6)): Listen queue overflow: 193 already in queue awaiting acceptance (17 occurrences), euid 80, rgid 80, jail 0
Mar 29 00:46:53 firewall kernel: [9615790] sonewconn: pcb 0xfffff801ca667a80 ([::]:8443 (proto 6)): Listen queue overflow: 193 already in queue awaiting acceptance (17 occurrences), euid 80, rgid 80, jail 0
Mar 29 00:48:00 firewall kernel: [9615857] sonewconn: pcb 0xfffff801ca667a80 ([::]:8443 (proto 6)): Listen queue overflow: 193 already in queue awaiting acceptance (72 occurrences), euid 80, rgid 80, jail 0
Mar 29 00:48:00 firewall kernel: [9615857] sonewconn: pcb 0xfffff801ca667a80 ([::]:8443 (proto 6)): Listen queue overflow: 193 already in queue awaiting acceptance (72 occurrences), euid 80, rgid 80, jail 0

8443 used by rtorrent, it run under www user. I have no idea why only IPv6 connections have queue overflow.

I past I see errors like that, this happen due to wrong app arch:

void some_listen_socket_accept_cb(...) {
   int fd_new = accept(fd_listen);
   if (-1 != fd_new) {
       // do something
   } else {
      // log error
   }
}

Problem here it that listen socket may have more than 1 incoming connection in queue and event trigger system set to triggen only on new connections. In that case queue will grow until max_backlog reached.

void some_listen_socket_accept_cb(...) {
   for (;;) {
      int fd_new = accept(fd_listen);
      if (-1 != fd_new) {
          // do something
      } else {
         if (errno == EWOULDBLOCK || errno == EAGAIN)
            break; /* all connections accepted. */
         // log error
      }
   }
}

This simple modification allow to be sure that all connections from listen queue will be accepted before return to next event wait.

rozhuk-im avatar Mar 31 '25 23:03 rozhuk-im