Changeset 209 in code for trunk/upstream.go


Ignore:
Timestamp:
Apr 3, 2020, 2:15:25 PM (5 years ago)
Author:
contact
Message:

Fix writer goroutine races

Any SendMessage call after Close could potentially block forever if the
outgoing channel was filled up. Now the channel is drained before the
writer goroutine exits.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/upstream.go

    r206 r209  
    114114
    115115        go func() {
    116                 // TODO: any SendMessage call after the connection is closed will
    117                 // either block or drop
    118                 for {
    119                         var closed bool
    120                         select {
    121                         case msg := <-outgoing:
    122                                 if uc.srv.Debug {
    123                                         uc.logger.Printf("sent: %v", msg)
    124                                 }
    125                                 uc.net.SetWriteDeadline(time.Now().Add(writeTimeout))
    126                                 if err := uc.irc.WriteMessage(msg); err != nil {
    127                                         uc.logger.Printf("failed to write message: %v", err)
    128                                         closed = true
    129                                 }
    130                         case <-uc.closed:
    131                                 closed = true
    132                         }
    133                         if closed {
     116                for msg := range outgoing {
     117                        if uc.srv.Debug {
     118                                uc.logger.Printf("sent: %v", msg)
     119                        }
     120                        uc.net.SetWriteDeadline(time.Now().Add(writeTimeout))
     121                        if err := uc.irc.WriteMessage(msg); err != nil {
     122                                uc.logger.Printf("failed to write message: %v", err)
    134123                                break
    135124                        }
     
    139128                } else {
    140129                        uc.logger.Printf("connection closed")
     130                }
     131                // Drain the outgoing channel to prevent SendMessage from blocking
     132                for range outgoing {
     133                        // This space is intentionally left blank
    141134                }
    142135        }()
     
    160153        }
    161154        close(uc.closed)
     155        close(uc.outgoing)
    162156        return nil
    163157}
Note: See TracChangeset for help on using the changeset viewer.