@@ -639,6 +639,37 @@ int anetUnixServer(char *err, char *path, mode_t perm, int backlog, char *group)
639
639
return s ;
640
640
}
641
641
642
+ /* For some error cases indicates transient errors and accept can be retried
643
+ * in order to serve other pending connections. This function should be called with the last errno,
644
+ * right after anetTcpaccept or anetUnixAccept returned an error in order to retry them. */
645
+ int anetRetryAcceptOnError (int err ) {
646
+ /* This is a transient error which can happen, for example, when
647
+ * a client initiates a TCP handshake (SYN),
648
+ * the server receives and queues it in the pending connections queue (the SYN queue),
649
+ * but before accept() is called, the connection is aborted.
650
+ * in such cases we can continue accepting other connections. ß*/
651
+ if (err == ECONNABORTED )
652
+ return 1 ;
653
+
654
+ #if defined(__linux__ )
655
+ /* https://www.man7.org/linux/man-pages/man2/accept4.2 suggests that:
656
+ * Linux accept() (and accept4()) passes already-pending network
657
+ errors on the new socket as an error code from accept(). This
658
+ behavior differs from other BSD socket implementations. For
659
+ reliable operation the application should detect the network
660
+ errors defined for the protocol after accept() and treat them like
661
+ EAGAIN by retrying. In the case of TCP/IP, these are ENETDOWN,
662
+ EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP,
663
+ and ENETUNREACH. */
664
+ if (err == ENETDOWN || err == EPROTO || err == ENOPROTOOPT ||
665
+ err == EHOSTDOWN || err == ENONET || err == EHOSTUNREACH ||
666
+ err == EOPNOTSUPP || err == ENETUNREACH ) {
667
+ return 1 ;
668
+ }
669
+ #endif
670
+ return 0 ;
671
+ }
672
+
642
673
/* Accept a connection and also make sure the socket is non-blocking, and CLOEXEC.
643
674
* returns the new socket FD, or -1 on error. */
644
675
static int anetGenericAccept (char * err , int s , struct sockaddr * sa , socklen_t * len ) {
0 commit comments