doumu9799 2018-08-28 21:46
浏览 67

Goroutines:广播者在收到第一条消息后停止工作

I use a server to broadcast / echo messages from clients to all connected clients. The server only broadcasts the first message it receives, although it still receives messages - as fmt.Println([]byte(buf)) still prints new messages from the clients - and new clients can connect (but their messages also won't be broadcasted).

After some feedback, it looks like one goroutine is stuck. But so far I've been unable to find which one. Help is really appreciated.

The server:

package main

import (
    "crypto/tls"
    "encoding/binary"
    "fmt"
    "io"
    "log"
    "net"
    "net/http"
    _ "net/http/pprof"
)

type client chan<- string // an outgoing message channel

var (
    entering = make(chan client, 10)
    leaving  = make(chan client, 10)
    messages = make(chan string, 10) // all incoming client messages
)

func broadcaster() {
    clients := make(map[client]bool) // all connected clients
    for {
        select {
        case msg := <-messages:
            // Broadcast incoming message to all clients' outgoing message channels.
            for cli := range clients {
                cli <- string(msg)
            }
        case cli := <-entering:
            clients[cli] = true

        case cli := <-leaving:
            delete(clients, cli)
            close(cli)

        }

    }
}

func handleConn(conn net.Conn) {

    ch := make(chan string) // outgoing client messages
    go clientWriter(conn, ch)
    defer conn.Close()
    entering <- ch

    buf := make([]byte, 0, 2+64*1024)
    for {
        n, err := io.ReadFull(conn, buf[:2])
        if err != nil {
            fmt.Println(n, err)
            leaving <- ch
            return
        }
        msgLen := binary.BigEndian.Uint16(buf[0:2])
        buf = buf[0 : 2+msgLen]
        n, err = io.ReadFull(conn, buf[2:2+msgLen])
        if err != nil {
            fmt.Println(err)
            leaving <- ch
            return
        }
        messages <- string(buf)
        fmt.Println([]byte(buf))

    }
}

func clientWriter(conn net.Conn, ch <-chan string) {
    for msg := range ch {
        _, err := fmt.Fprintln(conn, msg)
        if err != nil {
            fmt.Println(err)
        }
    }
}

func main() {
    go func() {
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }()

    cer, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
    if err != nil {
        log.Println(err)
        return
    }

    config := &tls.Config{
        Certificates: []tls.Certificate{cer},
        // Reject any TLS certificate that cannot be validated
        //ClientAuth: tls.RequireAndVerifyClientCert,
        // PFS, this will reject client with RSA certificates
        CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
        // Force it server side
        PreferServerCipherSuites: true,
        // TLS 1.2
        MinVersion: tls.VersionTLS12}

    listener, err := tls.Listen("tcp", "localhost:443", config)
    if err != nil {
        log.Fatal(err)
    }
    go broadcaster()
    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Print(err)
            continue
        }

        go handleConn(conn)
    }
}

My best guess is that the message channel is stuck - but I can't identify where. Help is really appreciated.

The client sends []bytes with [0, encrypted-message-length, encrypted-message], e.g. [0 52 155 84 146 8 228 90 28 41 88 33 178 143 243 243 160 255 180 73 20 43 129 155 132 255 207 10 9 130 54 216 44 38 141 101 17 125 101 4 62 228 221 158 196 41 163 227 253 71 179 172 143 225]

Update1: Sorry, I'm not good in debugging. Here are the full goroutine stack dumps (working and not working). The difference seems to me, that goroutine 8 was "runnable", while goroutine 9 is "IO wait" with "runtime_pollWait". Any ideas how to resolve it?

After server starts: Without any prior input from client (except connecting). In this state, the broadcast will work once.

   goroutine 12 [running]:
runtime/pprof.writeGoroutineStacks(0x7da840, 0xc42035e0e0, 0x411a69, 0xc420150570)
    /usr/lib/go-1.10/src/runtime/pprof/pprof.go:650 +0xa7
runtime/pprof.writeGoroutine(0x7da840, 0xc42035e0e0, 0x2, 0xc42006c000, 0x7da640)
    /usr/lib/go-1.10/src/runtime/pprof/pprof.go:639 +0x44
runtime/pprof.(*Profile).WriteTo(0x980840, 0x7da840, 0xc42035e0e0, 0x2, 0xc42035e0e0, 0x7998f5)
    /usr/lib/go-1.10/src/runtime/pprof/pprof.go:310 +0x3e4
net/http/pprof.handler.ServeHTTP(0xc42001a0a1, 0x9, 0x7dd620, 0xc42035e0e0, 0xc420254200)
    /usr/lib/go-1.10/src/net/http/pprof/pprof.go:243 +0x20d
net/http/pprof.Index(0x7dd620, 0xc42035e0e0, 0xc420254200)
    /usr/lib/go-1.10/src/net/http/pprof/pprof.go:254 +0x1d1
net/http.HandlerFunc.ServeHTTP(0x7b02a8, 0x7dd620, 0xc42035e0e0, 0xc420254200)
    /usr/lib/go-1.10/src/net/http/server.go:1947 +0x44
net/http.(*ServeMux).ServeHTTP(0x98dda0, 0x7dd620, 0xc42035e0e0, 0xc420254200)
    /usr/lib/go-1.10/src/net/http/server.go:2337 +0x130
net/http.serverHandler.ServeHTTP(0xc42016c000, 0x7dd620, 0xc42035e0e0, 0xc420254200)
    /usr/lib/go-1.10/src/net/http/server.go:2694 +0xbc
net/http.(*conn).serve(0xc4201640a0, 0x7dd8e0, 0xc42014c300)
    /usr/lib/go-1.10/src/net/http/server.go:1830 +0x651
created by net/http.(*Server).Serve
    /usr/lib/go-1.10/src/net/http/server.go:2795 +0x27b

goroutine 1 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8e30, 0x72, 0x0)
    /usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc4201b0118, 0x72, 0xc4200a2000, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc4201b0118, 0xffffffffffffff00, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Accept(0xc4201b0100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372 +0x1a8
net.(*netFD).accept(0xc4201b0100, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/net/fd_unix.go:238 +0x42
net.(*TCPListener).accept(0xc42000e018, 0x4122b8, 0x380, 0x78f260)
    /usr/lib/go-1.10/src/net/tcpsock_posix.go:136 +0x2e
net.(*TCPListener).Accept(0xc42000e018, 0x4356c4, 0xc420181da0, 0x457610, 0xc420181de0)
    /usr/lib/go-1.10/src/net/tcpsock.go:259 +0x49
crypto/tls.(*listener).Accept(0xc42010cd80, 0x7afee0, 0x7ded20, 0xc4200e6000, 0x0)
    /usr/lib/go-1.10/src/crypto/tls/tls.go:52 +0x37
main.main()
    /home/hendrik/Dropbox/go/chat/server/server.go:109 +0x2ca

goroutine 20 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8d60, 0x72, 0xc42020baa8)
    /usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc42015c098, 0x72, 0xffffffffffffff00, 0x7db3a0, 0x9515e0)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc42015c098, 0xc4200d6400, 0x400, 0x400)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Read(0xc42015c080, 0xc4200d6400, 0x400, 0x400, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_unix.go:157 +0x17d
net.(*netFD).Read(0xc42015c080, 0xc4200d6400, 0x400, 0x400, 0x57515a, 0xc42015c080, 0xc420202180)
    /usr/lib/go-1.10/src/net/fd_unix.go:202 +0x4f
net.(*conn).Read(0xc420156020, 0xc4200d6400, 0x400, 0x400, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/net/net.go:176 +0x6a
crypto/tls.(*block).readFromUntil(0xc420150330, 0x7f84564feae0, 0xc420156020, 0x5, 0xc420156020, 0x5d626a)
    /usr/lib/go-1.10/src/crypto/tls/conn.go:493 +0x96
crypto/tls.(*Conn).readRecord(0xc4200e6000, 0x7b0717, 0xc4200e6120, 0x98b7c0)
    /usr/lib/go-1.10/src/crypto/tls/conn.go:595 +0xe0
crypto/tls.(*Conn).Read(0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/crypto/tls/conn.go:1156 +0x100
io.ReadAtLeast(0x7f84564feac0, 0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x2, 0x786f60, 0x6d8e00, 0x7f84564feac0)
    /usr/lib/go-1.10/src/io/io.go:309 +0x86
io.ReadFull(0x7f84564feac0, 0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x10002, 0x6863ee, 0x1)
    /usr/lib/go-1.10/src/io/io.go:327 +0x58
main.handleConn(0x7ded20, 0xc4200e6000)
    /home/hendrik/Dropbox/go/chat/server/server.go:52 +0x27d
created by main.main
    /home/hendrik/Dropbox/go/chat/server/server.go:115 +0x350

goroutine 4 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8f00, 0x72, 0x0)
    /usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc4201b0098, 0x72, 0xc42014c000, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc4201b0098, 0xffffffffffffff00, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Accept(0xc4201b0080, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372 +0x1a8
net.(*netFD).accept(0xc4201b0080, 0xc420164120, 0xc42003edf0, 0x402b98)
    /usr/lib/go-1.10/src/net/fd_unix.go:238 +0x42
net.(*TCPListener).accept(0xc420156048, 0xc42003ee20, 0x401af7, 0xc420164120)
    /usr/lib/go-1.10/src/net/tcpsock_posix.go:136 +0x2e
net.(*TCPListener).AcceptTCP(0xc420156048, 0xc42003ee68, 0xc42003ee70, 0x18)
    /usr/lib/go-1.10/src/net/tcpsock.go:246 +0x49
net/http.tcpKeepAliveListener.Accept(0xc420156048, 0x7b00a8, 0xc4201640a0, 0x7dd9a0, 0xc420150750)
    /usr/lib/go-1.10/src/net/http/server.go:3216 +0x2f
net/http.(*Server).Serve(0xc42016c000, 0x7dd820, 0xc420156048, 0x0, 0x0)
    /usr/lib/go-1.10/src/net/http/server.go:2770 +0x1a5
net/http.(*Server).ListenAndServe(0xc42016c000, 0xc42016c000, 0x0)
    /usr/lib/go-1.10/src/net/http/server.go:2711 +0xa9
net/http.ListenAndServe(0x79a39f, 0xe, 0x0, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/net/http/server.go:2969 +0x7a
main.main.func1()
    /home/hendrik/Dropbox/go/chat/server/server.go:83 +0x3e
created by main.main
    /home/hendrik/Dropbox/go/chat/server/server.go:82 +0x4a

goroutine 36 [runnable]:
net/http.(*connReader).backgroundRead(0xc4201508d0)
    /usr/lib/go-1.10/src/net/http/server.go:667
created by net/http.(*connReader).startBackgroundRead
    /usr/lib/go-1.10/src/net/http/server.go:664 +0xce

goroutine 11 [select]:
main.broadcaster()
    /home/hendrik/Dropbox/go/chat/server/server.go:25 +0x193
created by main.main
    /home/hendrik/Dropbox/go/chat/server/server.go:107 +0x2b0

goroutine 21 [chan receive]:
main.clientWriter(0x7ded20, 0xc4200e6000, 0xc42007a120)
    /home/hendrik/Dropbox/go/chat/server/server.go:73 +0x52
created by main.handleConn
    /home/hendrik/Dropbox/go/chat/server/server.go:46 +0x89

after one broadcast (broadcast won't work): This is the state after one broadcast. Server won't broadcast any more messages.

 goroutine 12 [running]:
runtime/pprof.writeGoroutineStacks(0x7da840, 0xc42035e1c0, 0x411a69, 0xc4201507e0)
    /usr/lib/go-1.10/src/runtime/pprof/pprof.go:650 +0xa7
runtime/pprof.writeGoroutine(0x7da840, 0xc42035e1c0, 0x2, 0xc420468000, 0x7da640)
    /usr/lib/go-1.10/src/runtime/pprof/pprof.go:639 +0x44
runtime/pprof.(*Profile).WriteTo(0x980840, 0x7da840, 0xc42035e1c0, 0x2, 0xc42035e1c0, 0x7998f5)
    /usr/lib/go-1.10/src/runtime/pprof/pprof.go:310 +0x3e4
net/http/pprof.handler.ServeHTTP(0xc42001a2e1, 0x9, 0x7dd620, 0xc42035e1c0, 0xc420146100)
    /usr/lib/go-1.10/src/net/http/pprof/pprof.go:243 +0x20d
net/http/pprof.Index(0x7dd620, 0xc42035e1c0, 0xc420146100)
    /usr/lib/go-1.10/src/net/http/pprof/pprof.go:254 +0x1d1
net/http.HandlerFunc.ServeHTTP(0x7b02a8, 0x7dd620, 0xc42035e1c0, 0xc420146100)
    /usr/lib/go-1.10/src/net/http/server.go:1947 +0x44
net/http.(*ServeMux).ServeHTTP(0x98dda0, 0x7dd620, 0xc42035e1c0, 0xc420146100)
    /usr/lib/go-1.10/src/net/http/server.go:2337 +0x130
net/http.serverHandler.ServeHTTP(0xc42016c000, 0x7dd620, 0xc42035e1c0, 0xc420146100)
    /usr/lib/go-1.10/src/net/http/server.go:2694 +0xbc
net/http.(*conn).serve(0xc4201640a0, 0x7dd8e0, 0xc42014c300)
    /usr/lib/go-1.10/src/net/http/server.go:1830 +0x651
created by net/http.(*Server).Serve
    /usr/lib/go-1.10/src/net/http/server.go:2795 +0x27b

goroutine 1 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8e30, 0x72, 0x0)
    /usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc4201b0118, 0x72, 0xc4200a2000, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc4201b0118, 0xffffffffffffff00, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Accept(0xc4201b0100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372 +0x1a8
net.(*netFD).accept(0xc4201b0100, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/net/fd_unix.go:238 +0x42
net.(*TCPListener).accept(0xc42000e018, 0x4122b8, 0x380, 0x78f260)
    /usr/lib/go-1.10/src/net/tcpsock_posix.go:136 +0x2e
net.(*TCPListener).Accept(0xc42000e018, 0x4356c4, 0xc420181da0, 0x457610, 0xc420181de0)
    /usr/lib/go-1.10/src/net/tcpsock.go:259 +0x49
crypto/tls.(*listener).Accept(0xc42010cd80, 0x7afee0, 0x7ded20, 0xc4200e6000, 0x0)
    /usr/lib/go-1.10/src/crypto/tls/tls.go:52 +0x37
main.main()
    /home/hendrik/Dropbox/go/chat/server/server.go:109 +0x2ca

goroutine 20 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8d60, 0x72, 0xc42020baa8)
    /usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc42015c098, 0x72, 0xffffffffffffff00, 0x7db3a0, 0x9515e0)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc42015c098, 0xc4200d6400, 0x400, 0x400)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Read(0xc42015c080, 0xc4200d6400, 0x400, 0x400, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_unix.go:157 +0x17d
net.(*netFD).Read(0xc42015c080, 0xc4200d6400, 0x400, 0x400, 0x2, 0x80, 0x82)
    /usr/lib/go-1.10/src/net/fd_unix.go:202 +0x4f
net.(*conn).Read(0xc420156020, 0xc4200d6400, 0x400, 0x400, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/net/net.go:176 +0x6a
crypto/tls.(*block).readFromUntil(0xc420150330, 0x7f84564feae0, 0xc420156020, 0x5, 0xc420156020, 0x1)
    /usr/lib/go-1.10/src/crypto/tls/conn.go:493 +0x96
crypto/tls.(*Conn).readRecord(0xc4200e6000, 0x7b0717, 0xc4200e6120, 0x0)
    /usr/lib/go-1.10/src/crypto/tls/conn.go:595 +0xe0
crypto/tls.(*Conn).Read(0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/crypto/tls/conn.go:1156 +0x100
io.ReadAtLeast(0x7f84564feac0, 0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x2, 0x786f60, 0x0, 0x7f84564feac0)
    /usr/lib/go-1.10/src/io/io.go:309 +0x86
io.ReadFull(0x7f84564feac0, 0xc4200e6000, 0xc4201e6000, 0x2, 0x10002, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/io/io.go:327 +0x58
main.handleConn(0x7ded20, 0xc4200e6000)
    /home/hendrik/Dropbox/go/chat/server/server.go:52 +0x27d
created by main.main
    /home/hendrik/Dropbox/go/chat/server/server.go:115 +0x350

goroutine 4 [IO wait]:
internal/poll.runtime_pollWait(0x7f84564f8f00, 0x72, 0x0)
    /usr/lib/go-1.10/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc4201b0098, 0x72, 0xc42014c000, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc4201b0098, 0xffffffffffffff00, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Accept(0xc4201b0080, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372 +0x1a8
net.(*netFD).accept(0xc4201b0080, 0xc420164120, 0xc42003edf0, 0x402b98)
    /usr/lib/go-1.10/src/net/fd_unix.go:238 +0x42
net.(*TCPListener).accept(0xc420156048, 0xc42003ee20, 0x401af7, 0xc420164120)
    /usr/lib/go-1.10/src/net/tcpsock_posix.go:136 +0x2e
net.(*TCPListener).AcceptTCP(0xc420156048, 0xc42003ee68, 0xc42003ee70, 0x18)
    /usr/lib/go-1.10/src/net/tcpsock.go:246 +0x49
net/http.tcpKeepAliveListener.Accept(0xc420156048, 0x7b00a8, 0xc4201640a0, 0x7dd9a0, 0xc420150750)
    /usr/lib/go-1.10/src/net/http/server.go:3216 +0x2f
net/http.(*Server).Serve(0xc42016c000, 0x7dd820, 0xc420156048, 0x0, 0x0)
    /usr/lib/go-1.10/src/net/http/server.go:2770 +0x1a5
net/http.(*Server).ListenAndServe(0xc42016c000, 0xc42016c000, 0x0)
    /usr/lib/go-1.10/src/net/http/server.go:2711 +0xa9
net/http.ListenAndServe(0x79a39f, 0xe, 0x0, 0x0, 0x0, 0x0)
    /usr/lib/go-1.10/src/net/http/server.go:2969 +0x7a
main.main.func1()
    /home/hendrik/Dropbox/go/chat/server/server.go:83 +0x3e
created by main.main
    /home/hendrik/Dropbox/go/chat/server/server.go:82 +0x4a

goroutine 37 [runnable]:
net/http.(*connReader).backgroundRead(0xc4201508d0)
    /usr/lib/go-1.10/src/net/http/server.go:667
created by net/http.(*connReader).startBackgroundRead
    /usr/lib/go-1.10/src/net/http/server.go:664 +0xce

goroutine 11 [select]:
main.broadcaster()
    /home/hendrik/Dropbox/go/chat/server/server.go:25 +0x193
created by main.main
    /home/hendrik/Dropbox/go/chat/server/server.go:107 +0x2b0

goroutine 21 [chan receive]:
main.clientWriter(0x7ded20, 0xc4200e6000, 0xc42007a120)
    /home/hendrik/Dropbox/go/chat/server/server.go:73 +0x52
created by main.handleConn
    /home/hendrik/Dropbox/go/chat/server/server.go:46 +0x89

goroutine profile: total 7 - before any messages

1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d7e5d 0x563dcf 0x574eda 0x5c5096 0x5c55a0 0x5c8b40 0x471196 0x471308 0x6d907d 0x45ab71
#   0x428ae6    internal/poll.runtime_pollWait+0x56 /usr/lib/go-1.10/src/runtime/netpoll.go:173
#   0x4d6f7a    internal/poll.(*pollDesc).wait+0x9a /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
#   0x4d6ffc    internal/poll.(*pollDesc).waitRead+0x3c /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
#   0x4d7e5c    internal/poll.(*FD).Read+0x17c      /usr/lib/go-1.10/src/internal/poll/fd_unix.go:157
#   0x563dce    net.(*netFD).Read+0x4e          /usr/lib/go-1.10/src/net/fd_unix.go:202
#   0x574ed9    net.(*conn).Read+0x69           /usr/lib/go-1.10/src/net/net.go:176
#   0x5c5095    crypto/tls.(*block).readFromUntil+0x95  /usr/lib/go-1.10/src/crypto/tls/conn.go:493
#   0x5c559f    crypto/tls.(*Conn).readRecord+0xdf  /usr/lib/go-1.10/src/crypto/tls/conn.go:595
#   0x5c8b3f    crypto/tls.(*Conn).Read+0xff        /usr/lib/go-1.10/src/crypto/tls/conn.go:1156
#   0x471195    io.ReadAtLeast+0x85         /usr/lib/go-1.10/src/io/io.go:309
#   0x471307    io.ReadFull+0x57            /usr/lib/go-1.10/src/io/io.go:327
#   0x6d907c    main.handleConn+0x27c           /home/hendrik/Dropbox/go/chat/server/server.go:52

1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d93f8 0x5646e2 0x57e85e 0x57ce39 0x66271f 0x6614b5 0x661209 0x66224a 0x6d98ae 0x45ab71
#   0x428ae6    internal/poll.runtime_pollWait+0x56     /usr/lib/go-1.10/src/runtime/netpoll.go:173
#   0x4d6f7a    internal/poll.(*pollDesc).wait+0x9a     /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
#   0x4d6ffc    internal/poll.(*pollDesc).waitRead+0x3c     /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
#   0x4d93f7    internal/poll.(*FD).Accept+0x1a7        /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372
#   0x5646e1    net.(*netFD).accept+0x41            /usr/lib/go-1.10/src/net/fd_unix.go:238
#   0x57e85d    net.(*TCPListener).accept+0x2d          /usr/lib/go-1.10/src/net/tcpsock_posix.go:136
#   0x57ce38    net.(*TCPListener).AcceptTCP+0x48       /usr/lib/go-1.10/src/net/tcpsock.go:246
#   0x66271e    net/http.tcpKeepAliveListener.Accept+0x2e   /usr/lib/go-1.10/src/net/http/server.go:3216
#   0x6614b4    net/http.(*Server).Serve+0x1a4          /usr/lib/go-1.10/src/net/http/server.go:2770
#   0x661208    net/http.(*Server).ListenAndServe+0xa8      /usr/lib/go-1.10/src/net/http/server.go:2711
#   0x662249    net/http.ListenAndServe+0x79            /usr/lib/go-1.10/src/net/http/server.go:2969
#   0x6d98ad    main.main.func1+0x3d                /home/hendrik/Dropbox/go/chat/server/server.go:83

1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d93f8 0x5646e2 0x57e85e 0x57d049 0x5e2bd7 0x6d973a 0x42dcf2 0x45ab71
#   0x428ae6    internal/poll.runtime_pollWait+0x56 /usr/lib/go-1.10/src/runtime/netpoll.go:173
#   0x4d6f7a    internal/poll.(*pollDesc).wait+0x9a /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
#   0x4d6ffc    internal/poll.(*pollDesc).waitRead+0x3c /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
#   0x4d93f7    internal/poll.(*FD).Accept+0x1a7    /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372
#   0x5646e1    net.(*netFD).accept+0x41        /usr/lib/go-1.10/src/net/fd_unix.go:238
#   0x57e85d    net.(*TCPListener).accept+0x2d      /usr/lib/go-1.10/src/net/tcpsock_posix.go:136
#   0x57d048    net.(*TCPListener).Accept+0x48      /usr/lib/go-1.10/src/net/tcpsock.go:259
#   0x5e2bd6    crypto/tls.(*listener).Accept+0x36  /usr/lib/go-1.10/src/crypto/tls/tls.go:52
#   0x6d9739    main.main+0x2c9             /home/hendrik/Dropbox/go/chat/server/server.go:109
#   0x42dcf1    runtime.main+0x211          /usr/lib/go-1.10/src/runtime/proc.go:198

1 @ 0x42e14a 0x42e1fe 0x405f92 0x405c8b 0x6d9342 0x45ab71
#   0x6d9341    main.clientWriter+0x51  /home/hendrik/Dropbox/go/chat/server/server.go:73

1 @ 0x42e14a 0x43db50 0x6d8cb3 0x45ab71
#   0x6d8cb2    main.broadcaster+0x192  /home/hendrik/Dropbox/go/chat/server/server.go:25

1 @ 0x657e40 0x45ab71
#   0x657e40    net/http.(*connReader).backgroundRead+0x0   /usr/lib/go-1.10/src/net/http/server.go:667

1 @ 0x6d0408 0x6d0210 0x6ccd54 0x6d851d 0x6d88a1 0x65e444 0x6600b0 0x6610ec 0x65d461 0x45ab71
#   0x6d0407    runtime/pprof.writeRuntimeProfile+0x97  /usr/lib/go-1.10/src/runtime/pprof/pprof.go:679
#   0x6d020f    runtime/pprof.writeGoroutine+0x9f   /usr/lib/go-1.10/src/runtime/pprof/pprof.go:641
#   0x6ccd53    runtime/pprof.(*Profile).WriteTo+0x3e3  /usr/lib/go-1.10/src/runtime/pprof/pprof.go:310
#   0x6d851c    net/http/pprof.handler.ServeHTTP+0x20c  /usr/lib/go-1.10/src/net/http/pprof/pprof.go:243
#   0x6d88a0    net/http/pprof.Index+0x1d0      /usr/lib/go-1.10/src/net/http/pprof/pprof.go:254
#   0x65e443    net/http.HandlerFunc.ServeHTTP+0x43 /usr/lib/go-1.10/src/net/http/server.go:1947
#   0x6600af    net/http.(*ServeMux).ServeHTTP+0x12f    /usr/lib/go-1.10/src/net/http/server.go:2337
#   0x6610eb    net/http.serverHandler.ServeHTTP+0xbb   /usr/lib/go-1.10/src/net/http/server.go:2694
#   0x65d460    net/http.(*conn).serve+0x650        /usr/lib/go-1.10/src/net/http/server.go:1830

goroutine profile: total 7 - after first broadcast - not broadcasting any more

1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d7e5d 0x563dcf 0x574eda 0x5c5096 0x5c55a0 0x5c8b40 0x471196 0x471308 0x6d907d 0x45ab71
#   0x428ae6    internal/poll.runtime_pollWait+0x56 /usr/lib/go-1.10/src/runtime/netpoll.go:173
#   0x4d6f7a    internal/poll.(*pollDesc).wait+0x9a /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
#   0x4d6ffc    internal/poll.(*pollDesc).waitRead+0x3c /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
#   0x4d7e5c    internal/poll.(*FD).Read+0x17c      /usr/lib/go-1.10/src/internal/poll/fd_unix.go:157
#   0x563dce    net.(*netFD).Read+0x4e          /usr/lib/go-1.10/src/net/fd_unix.go:202
#   0x574ed9    net.(*conn).Read+0x69           /usr/lib/go-1.10/src/net/net.go:176
#   0x5c5095    crypto/tls.(*block).readFromUntil+0x95  /usr/lib/go-1.10/src/crypto/tls/conn.go:493
#   0x5c559f    crypto/tls.(*Conn).readRecord+0xdf  /usr/lib/go-1.10/src/crypto/tls/conn.go:595
#   0x5c8b3f    crypto/tls.(*Conn).Read+0xff        /usr/lib/go-1.10/src/crypto/tls/conn.go:1156
#   0x471195    io.ReadAtLeast+0x85         /usr/lib/go-1.10/src/io/io.go:309
#   0x471307    io.ReadFull+0x57            /usr/lib/go-1.10/src/io/io.go:327
#   0x6d907c    main.handleConn+0x27c           /home/hendrik/Dropbox/go/chat/server/server.go:52

1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d93f8 0x5646e2 0x57e85e 0x57ce39 0x66271f 0x6614b5 0x661209 0x66224a 0x6d98ae 0x45ab71
#   0x428ae6    internal/poll.runtime_pollWait+0x56     /usr/lib/go-1.10/src/runtime/netpoll.go:173
#   0x4d6f7a    internal/poll.(*pollDesc).wait+0x9a     /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
#   0x4d6ffc    internal/poll.(*pollDesc).waitRead+0x3c     /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
#   0x4d93f7    internal/poll.(*FD).Accept+0x1a7        /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372
#   0x5646e1    net.(*netFD).accept+0x41            /usr/lib/go-1.10/src/net/fd_unix.go:238
#   0x57e85d    net.(*TCPListener).accept+0x2d          /usr/lib/go-1.10/src/net/tcpsock_posix.go:136
#   0x57ce38    net.(*TCPListener).AcceptTCP+0x48       /usr/lib/go-1.10/src/net/tcpsock.go:246
#   0x66271e    net/http.tcpKeepAliveListener.Accept+0x2e   /usr/lib/go-1.10/src/net/http/server.go:3216
#   0x6614b4    net/http.(*Server).Serve+0x1a4          /usr/lib/go-1.10/src/net/http/server.go:2770
#   0x661208    net/http.(*Server).ListenAndServe+0xa8      /usr/lib/go-1.10/src/net/http/server.go:2711
#   0x662249    net/http.ListenAndServe+0x79            /usr/lib/go-1.10/src/net/http/server.go:2969
#   0x6d98ad    main.main.func1+0x3d                /home/hendrik/Dropbox/go/chat/server/server.go:83

1 @ 0x42e14a 0x42946a 0x428ae7 0x4d6f7b 0x4d6ffd 0x4d93f8 0x5646e2 0x57e85e 0x57d049 0x5e2bd7 0x6d973a 0x42dcf2 0x45ab71
#   0x428ae6    internal/poll.runtime_pollWait+0x56 /usr/lib/go-1.10/src/runtime/netpoll.go:173
#   0x4d6f7a    internal/poll.(*pollDesc).wait+0x9a /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:85
#   0x4d6ffc    internal/poll.(*pollDesc).waitRead+0x3c /usr/lib/go-1.10/src/internal/poll/fd_poll_runtime.go:90
#   0x4d93f7    internal/poll.(*FD).Accept+0x1a7    /usr/lib/go-1.10/src/internal/poll/fd_unix.go:372
#   0x5646e1    net.(*netFD).accept+0x41        /usr/lib/go-1.10/src/net/fd_unix.go:238
#   0x57e85d    net.(*TCPListener).accept+0x2d      /usr/lib/go-1.10/src/net/tcpsock_posix.go:136
#   0x57d048    net.(*TCPListener).Accept+0x48      /usr/lib/go-1.10/src/net/tcpsock.go:259
#   0x5e2bd6    crypto/tls.(*listener).Accept+0x36  /usr/lib/go-1.10/src/crypto/tls/tls.go:52
#   0x6d9739    main.main+0x2c9             /home/hendrik/Dropbox/go/chat/server/server.go:109
#   0x42dcf1    runtime.main+0x211          /usr/lib/go-1.10/src/runtime/proc.go:198

1 @ 0x42e14a 0x42e1fe 0x405f92 0x405c8b 0x6d9342 0x45ab71
#   0x6d9341    main.clientWriter+0x51  /home/hendrik/Dropbox/go/chat/server/server.go:73

1 @ 0x42e14a 0x43db50 0x6d8cb3 0x45ab71
#   0x6d8cb2    main.broadcaster+0x192  /home/hendrik/Dropbox/go/chat/server/server.go:25

1 @ 0x4c3195 0x4c10df 0x4bfa29 0x4d7df8 0x563dcf 0x574eda 0x657e9a 0x45ab71
#   0x4c3194    syscall.Syscall+0x4             /usr/lib/go-1.10/src/syscall/asm_linux_amd64.s:18
#   0x4c10de    syscall.read+0x5e               /usr/lib/go-1.10/src/syscall/zsyscall_linux_amd64.go:749
#   0x4bfa28    syscall.Read+0x48               /usr/lib/go-1.10/src/syscall/syscall_unix.go:162
#   0x4d7df7    internal/poll.(*FD).Read+0x117          /usr/lib/go-1.10/src/internal/poll/fd_unix.go:153
#   0x563dce    net.(*netFD).Read+0x4e              /usr/lib/go-1.10/src/net/fd_unix.go:202
#   0x574ed9    net.(*conn).Read+0x69               /usr/lib/go-1.10/src/net/net.go:176
#   0x657e99    net/http.(*connReader).backgroundRead+0x59  /usr/lib/go-1.10/src/net/http/server.go:668

1 @ 0x6d0408 0x6d0210 0x6ccd54 0x6d851d 0x6d88a1 0x65e444 0x6600b0 0x6610ec 0x65d461 0x45ab71
#   0x6d0407    runtime/pprof.writeRuntimeProfile+0x97  /usr/lib/go-1.10/src/runtime/pprof/pprof.go:679
#   0x6d020f    runtime/pprof.writeGoroutine+0x9f   /usr/lib/go-1.10/src/runtime/pprof/pprof.go:641
#   0x6ccd53    runtime/pprof.(*Profile).WriteTo+0x3e3  /usr/lib/go-1.10/src/runtime/pprof/pprof.go:310
#   0x6d851c    net/http/pprof.handler.ServeHTTP+0x20c  /usr/lib/go-1.10/src/net/http/pprof/pprof.go:243
#   0x6d88a0    net/http/pprof.Index+0x1d0      /usr/lib/go-1.10/src/net/http/pprof/pprof.go:254
#   0x65e443    net/http.HandlerFunc.ServeHTTP+0x43 /usr/lib/go-1.10/src/net/http/server.go:1947
#   0x6600af    net/http.(*ServeMux).ServeHTTP+0x12f    /usr/lib/go-1.10/src/net/http/server.go:2337
#   0x6610eb    net/http.serverHandler.ServeHTTP+0xbb   /usr/lib/go-1.10/src/net/http/server.go:2694
#   0x65d460    net/http.(*conn).serve+0x650        /usr/lib/go-1.10/src/net/http/server.go:1830
  • 写回答

1条回答 默认 最新

  • dongsun5330 2018-08-28 22:08
    关注

    Just a few comments on your code. You will have to test if that solves the problem:

    Having a defer in a for loop is never(?) a good idea. Move the defer into the handleConn function:

    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Print(err)
            continue
        }
        defer conn.Close() // Not good!
        go handleConn(conn)
    }
    

    Next I would play with the outgoing channel and make it a buffered channel:

    ch := make(chan string, 10) // outgoing client messages
    

    This has 2 effects:

    • Things will run faster/smoother as goroutines don't have to wait for the other side to be ready
    • This might solve your being stuck problem if there is a complex loop of goroutines each waiting on the other side that causes your issue.

    Do the same with all the other channels though I assume entering and leaving don't need it.

    EDIT:

    There is some error checking missing when writing to the connection. Maybe something goes wrong there:

    func clientWriter(conn net.Conn, ch <-chan string) {
        for msg := range ch {
            fmt.Fprintln(conn, msg) // add error checking here
        }
    }
    

    EDIT 2:

    Implement net/http/pprof server in your client and check the heap endpoint of the webserver it starts to see where the goroutines are hanging.

    评论

报告相同问题?

悬赏问题

  • ¥35 平滑拟合曲线该如何生成
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 自己瞎改改,结果现在又运行不了了
  • ¥15 链式存储应该如何解决
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站