{"record":{"id":"80fbcbda7d1937c8","repo":"ginuerzh/gost","slug":"accpet-on-closed-listener-80fbcb","errorCode":null,"errorMessage":"accpet on closed listener","messagePattern":"accpet on closed listener","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quic.go","lineNumber":239,"sourceCode":"\t\t}\n\n\t\tcc := &quicConn{Stream: stream, laddr: session.LocalAddr(), raddr: session.RemoteAddr()}\n\t\tselect {\n\t\tcase l.connChan <- cc:\n\t\tdefault:\n\t\t\tcc.Close()\n\t\t\tlog.Logf(\"[quic] %s - %s: connection queue is full\", session.RemoteAddr(), session.LocalAddr())\n\t\t}\n\t}\n}\n\nfunc (l *quicListener) Accept() (conn net.Conn, err error) {\n\tvar ok bool\n\tselect {\n\tcase conn = <-l.connChan:\n\tcase err, ok = <-l.errChan:\n\t\tif !ok {\n\t\t\terr = errors.New(\"accpet on closed listener\")\n\t\t}\n\t}\n\treturn\n}\n\nfunc (l *quicListener) Addr() net.Addr {\n\treturn l.ln.Addr()\n}\n\nfunc (l *quicListener) Close() error {\n\treturn l.ln.Close()\n}\n\ntype quicConn struct {\n\tquic.Stream\n\tladdr net.Addr\n\traddr net.Addr\n}","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/ginuerzh/gost/blob/a33fdbf4c98034f4bfeeaea9868909822b9c526d/quic.go#L221-L257","documentation":"quicListener.Accept returns this error when the listener's error channel is closed, meaning the underlying QUIC listener has been shut down. The channel-closed signal is converted into an explicit error so callers can distinguish 'listener closed' from a real accept failure.","triggerScenarios":"Calling Accept on a quicListener after Close() has been invoked (which closes l.errChan), so the select receives the zero error with ok == false.","commonSituations":"Accept loops that keep running after the server was shut down; a race between Close() and a pending/next Accept call in a connection-handling goroutine.","solutions":["Stop the Accept loop when this error is returned (standard pattern: return from the accept goroutine)","Ensure Close() is only called once and that shutdown logic terminates accept loops","If you didn't intend to close, find what closed the listener (supervisor, signal handler, parent context)"],"exampleFix":"// before\nfor {\n    conn, err := l.Accept()\n    if err != nil { log.Log(err); continue } // infinite loop on closed listener\n    go handle(conn)\n}\n// after\nfor {\n    conn, err := l.Accept()\n    if err != nil { return } // stop looping when listener is closed\n    go handle(conn)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"conn, err := l.Accept()\nif err != nil {\n    // listener closed or fatal accept error: stop the accept loop\n    return\n}","preventionTips":["Terminate accept goroutines on listener Close","Ensure Close is idempotent and coordinated with accept loops","Track listener lifecycle with a done channel/context"],"tags":["quic","listener","shutdown","lifecycle"],"backgroundTag":"use-of-closed-listener","analyzedSha":"a33fdbf4c98034f4bfeeaea9868909822b9c526d","analyzedAt":"2026-09-02T22:15:54.506Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}