Browse Source

Wait until we're done connecting before returning from fillPool, to avoid possible race between multiple goroutines opening new connections

Miles Delahunty 10 years ago
parent
commit
0033e98e26
1 changed files with 10 additions and 0 deletions
  1. 10 0
      connectionpool.go

+ 10 - 0
connectionpool.go

@@ -227,6 +227,8 @@ func (c *SimplePool) fillPool() {
 	c.hostMu.RLock()
 	c.hostMu.RLock()
 
 
 	//Walk through list of defined hosts
 	//Walk through list of defined hosts
+	cHostConnected := make(chan int, len(c.hosts))
+	hostsPending := 0
 	for host := range c.hosts {
 	for host := range c.hosts {
 		addr := JoinHostPort(host, c.cfg.Port)
 		addr := JoinHostPort(host, c.cfg.Port)
 
 
@@ -251,7 +253,9 @@ func (c *SimplePool) fillPool() {
 
 
 		//This is reached if the host is responsive and needs more connections
 		//This is reached if the host is responsive and needs more connections
 		//Create connections for host synchronously to mitigate flooding the host.
 		//Create connections for host synchronously to mitigate flooding the host.
+		hostsPending++
 		go func(a string, conns int) {
 		go func(a string, conns int) {
+			defer func() { cHostConnected <- 1 }()
 			for ; conns < c.cfg.NumConns; conns++ {
 			for ; conns < c.cfg.NumConns; conns++ {
 				c.connect(a)
 				c.connect(a)
 			}
 			}
@@ -259,6 +263,12 @@ func (c *SimplePool) fillPool() {
 	}
 	}
 
 
 	c.hostMu.RUnlock()
 	c.hostMu.RUnlock()
+
+	//Wait until we're finished connecting to each host before returning
+	for hostsPending > 0 {
+		<- cHostConnected
+		hostsPending--
+	}
 }
 }
 
 
 // Should only be called if c.mu is locked
 // Should only be called if c.mu is locked