Skip to content

Commit

Permalink
Use mutexes for byte counts to fix i386/arm panic.
Browse files Browse the repository at this point in the history
This commit changes the server byte counters over to use a mutex instead
of the atomic package.  The atomic.AddUint64 function requires the struct
fields to be 64-bit aligned on 32-bit platforms.  The byte counts are
fields in the server struct and are not 64-bit aligned.  While it would be
possible to arrange the fields to be aligned through various means, it
would make the code too fragile for my tastes.  I prefer code that doesn't
depend on platform specific alignment.

Fixes #96.
  • Loading branch information
davecgh committed Feb 13, 2014
1 parent f9922c7 commit e5a1c6e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
4 changes: 2 additions & 2 deletions peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ func (p *peer) handlePongMsg(msg *btcwire.MsgPong) {
func (p *peer) readMessage() (btcwire.Message, []byte, error) {
n, msg, buf, err := btcwire.ReadMessageN(p.conn, p.protocolVersion, p.btcnet)
p.bytesReceived += uint64(n)
atomic.AddUint64(&p.server.bytesReceived, uint64(n))
p.server.AddBytesReceived(uint64(n))
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -1025,7 +1025,7 @@ func (p *peer) writeMessage(msg btcwire.Message) {
// Write the message to the peer.
n, err := btcwire.WriteMessageN(p.conn, msg, p.protocolVersion, p.btcnet)
p.bytesSent += uint64(n)
atomic.AddUint64(&p.server.bytesSent, uint64(n))
p.server.AddBytesSent(uint64(n))
if err != nil {
p.Disconnect()
p.logError("Can't send message: %v", err)
Expand Down
38 changes: 29 additions & 9 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ type server struct {
nonce uint64
listeners []net.Listener
btcnet btcwire.BitcoinNet
started int32 // atomic
shutdown int32 // atomic
shutdownSched int32 // atomic
bytesReceived uint64 // Total bytes received from all peers since start.
bytesSent uint64 // Total bytes sent by all peers since start.
started int32 // atomic
shutdown int32 // atomic
shutdownSched int32 // atomic
bytesMutex sync.Mutex // For the following two fields.
bytesReceived uint64 // Total bytes received from all peers since start.
bytesSent uint64 // Total bytes sent by all peers since start.
addrManager *AddrManager
rpcServer *rpcServer
blockManager *blockManager
Expand Down Expand Up @@ -696,12 +697,31 @@ func (s *server) RemoveAddr(addr string) error {
return <-replyChan
}

// AddBytesSent adds the passed number of bytes to the total bytes sent counter
// for the server. It is safe for concurrent access.
func (s *server) AddBytesSent(bytesSent uint64) {
s.bytesMutex.Lock()
defer s.bytesMutex.Unlock()

s.bytesSent += bytesSent
}

// AddBytesReceived adds the passed number of bytes to the total bytes received
// counter for the server. It is safe for concurrent access.
func (s *server) AddBytesReceived(bytesReceived uint64) {
s.bytesMutex.Lock()
defer s.bytesMutex.Unlock()

s.bytesReceived += bytesReceived
}

// NetTotals returns the sum of all bytes received and sent across the network
// for all peers.
// for all peers. It is safe for concurrent access.
func (s *server) NetTotals() (uint64, uint64) {
totalBytesReceived := atomic.LoadUint64(&s.bytesReceived)
totalBytesSent := atomic.LoadUint64(&s.bytesSent)
return totalBytesReceived, totalBytesSent
s.bytesMutex.Lock()
defer s.bytesMutex.Unlock()

return s.bytesReceived, s.bytesSent
}

// Start begins accepting connections from peers.
Expand Down

0 comments on commit e5a1c6e

Please sign in to comment.