Changeset 175 in code for trunk/upstream.go


Ignore:
Timestamp:
Mar 27, 2020, 10:08:35 PM (5 years ago)
Author:
contact
Message:

Fix race condition in upstreamConn.Close

upstreamConn.closed was a bool accessed from different goroutines. Use
the same pattern as downstreamConn instead.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/upstream.go

    r174 r175  
    3737        user     *user
    3838        outgoing chan<- *irc.Message
     39        closed   chan struct{}
    3940
    4041        serverName            string
     
    4849        username   string
    4950        realname   string
    50         closed     bool
    5151        modes      userModes
    5252        channels   map[string]*upstreamChannel
     
    9696
    9797        go func() {
    98                 for msg := range outgoing {
    99                         if uc.srv.Debug {
    100                                 uc.logger.Printf("sent: %v", msg)
    101                         }
    102                         if err := uc.irc.WriteMessage(msg); err != nil {
    103                                 uc.logger.Printf("failed to write message: %v", err)
     98                for {
     99                        var closed bool
     100                        select {
     101                        case msg := <-outgoing:
     102                                if uc.srv.Debug {
     103                                        uc.logger.Printf("sent: %v", msg)
     104                                }
     105                                if err := uc.irc.WriteMessage(msg); err != nil {
     106                                        uc.logger.Printf("failed to write message: %v", err)
     107                                }
     108                        case <-uc.closed:
     109                                closed = true
     110                        }
     111                        if closed {
     112                                break
    104113                        }
    105114                }
     
    114123}
    115124
     125func (uc *upstreamConn) isClosed() bool {
     126        select {
     127        case <-uc.closed:
     128                return true
     129        default:
     130                return false
     131        }
     132}
     133
    116134func (uc *upstreamConn) Close() error {
    117         if uc.closed {
     135        if uc.isClosed() {
    118136                return fmt.Errorf("upstream connection already closed")
    119137        }
    120         close(uc.outgoing)
    121         uc.closed = true
     138        close(uc.closed)
    122139        return nil
    123140}
Note: See TracChangeset for help on using the changeset viewer.