{"record":{"id":"4637089af152f9f5","repo":"XX-net/XX-Net","slug":"except-s-send-blockingioerror-r","errorCode":null,"errorMessage":"Except %s send BlockingIOError %r","messagePattern":"Except (.+?) send BlockingIOError %r","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"code/default/smart_router/local/pipe_socks.py","lineNumber":281,"sourceCode":"                                self.close(s2, \"w\")\n                                continue\n                            except Exception as e:\n                                xlog.warn(\"send split SNI:%s fail:%r\", s2.host, e)\n                                self.close(s2, \"w\")\n                                continue\n\n                            s2.add_dat(d2)\n                            d = b\"\"\n                            xlog.debug(\"pipe send split SNI:%s\", s2.host)\n\n                    if s2.buf_size == 0:\n                        try:\n                            sent = s2.send(d)\n                            s2.sent_data += sent\n                            s2.sent_times += 1\n                            # xlog.debug(\"direct send %d to %s from:%s total:%d\", sent, s2, s1, len(d))\n                        except BlockingIOError as e:\n                            xlog.warn(\"Except %s send BlockingIOError %r\", s2, e)\n                            sent = 0\n                        except socket.error as e:\n                            if e.errno == errno.EAGAIN:\n                                # if str(e) == \"[Errno 35] Resource temporarily unavailable\":\n                                xlog.warn(\"%s send errno.EAGAIN %r\", s2, e)\n                                time.sleep(0.1)\n                                sent = 0\n                            else:\n                                self.close(s2, \"w\")\n                                continue\n                        except Exception as e:\n                            # xlog.debug(\"%s send e:%r\", s2, e)\n                            if sys.version_info[0] == 3 and isinstance(e, BlockingIOError):\n                                # This error happened on upload large file or speed test\n                                # Just ignore this error and will be fine\n                                xlog.warn(\"%s send BlockingIOError %r\", s2, e)\n                                sent = 0\n                            else:","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/XX-net/XX-Net/blob/cfa5bc17b67676e467f37ec50766127e0ab5f0aa/code/default/smart_router/local/pipe_socks.py#L263-L299","documentation":"s2.send() raised BlockingIOError on a non-blocking socket: the kernel send buffer is full and no bytes could be written. sent is set to 0 and the buffered-send path (with EAGAIN handling) takes over.","triggerScenarios":"Calling send() on a non-blocking socket whose send buffer is completely full; typical in the pipe relay loop when the remote drains slowly.","commonSituations":"High-throughput relaying to a slow remote; small SO_SNDBUF; burst traffic; peer application not reading.","solutions":["Rely on the subsequent EAGAIN/buffered-send path (already present) to queue the data","Increase SO_SNDBUF or apply backpressure to the reader side","Use select/epoll writability checks before sending","Close or deprioritize connections that stay unwritable too long"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if not writable(s2): wait_for_writable(s2)","typeGuard":null,"tryCatchPattern":"Treat BlockingIOError as sent=0 and queue for later flush; only close on repeated EAGAIN past a deadline.","preventionTips":["Check socket writability before send on non-blocking sockets","Cap per-connection unsent buffer to bound memory"],"tags":["network","non-blocking-socket","would-block","relay"],"backgroundTag":"socket-would-block","analyzedSha":"cfa5bc17b67676e467f37ec50766127e0ab5f0aa","analyzedAt":"2026-08-27T19:28:28.225Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}