Fix router race condition
This commit is contained in:
		| @@ -513,25 +513,28 @@ func (r *router) advertiseEvents() error { | |||||||
|  |  | ||||||
| // close closes exit channels | // close closes exit channels | ||||||
| func (r *router) close() { | func (r *router) close() { | ||||||
| 	// notify all goroutines to finish | 	log.Debugf("Router closing remaining channels") | ||||||
| 	close(r.exit) |  | ||||||
|  |  | ||||||
| 	// drain the advertise channel only if advertising | 	// drain the advertise channel only if advertising | ||||||
| 	if r.status.Code == Advertising { | 	if r.status.Code == Advertising { | ||||||
| 		// drain the event channel | 		// drain the event channel | ||||||
| 		for range r.eventChan { | 		for range r.eventChan { | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		r.sub.RLock() |  | ||||||
| 		// close advert subscribers | 		// close advert subscribers | ||||||
| 		for id, sub := range r.subscribers { | 		for id, sub := range r.subscribers { | ||||||
|  | 			select { | ||||||
|  | 			case <-sub: | ||||||
|  | 			default: | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			// close the channel | 			// close the channel | ||||||
| 			close(sub) | 			close(sub) | ||||||
|  |  | ||||||
| 			// delete the subscriber | 			// delete the subscriber | ||||||
|  | 			r.sub.Lock() | ||||||
| 			delete(r.subscribers, id) | 			delete(r.subscribers, id) | ||||||
|  | 			r.sub.Unlock() | ||||||
| 		} | 		} | ||||||
| 		r.sub.RUnlock() |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// mark the router as Stopped and set its Error to nil | 	// mark the router as Stopped and set its Error to nil | ||||||
| @@ -552,6 +555,9 @@ func (r *router) watchErrors() { | |||||||
| 	defer r.Unlock() | 	defer r.Unlock() | ||||||
| 	// if the router is not stopped, stop it | 	// if the router is not stopped, stop it | ||||||
| 	if r.status.Code != Stopped { | 	if r.status.Code != Stopped { | ||||||
|  | 		// notify all goroutines to finish | ||||||
|  | 		close(r.exit) | ||||||
|  |  | ||||||
| 		// close all the channels | 		// close all the channels | ||||||
| 		r.close() | 		r.close() | ||||||
| 		// set the status error | 		// set the status error | ||||||
| @@ -857,6 +863,9 @@ func (r *router) Stop() error { | |||||||
| 		r.Unlock() | 		r.Unlock() | ||||||
| 		return r.status.Error | 		return r.status.Error | ||||||
| 	case Running, Advertising: | 	case Running, Advertising: | ||||||
|  | 		// notify all goroutines to finish | ||||||
|  | 		close(r.exit) | ||||||
|  |  | ||||||
| 		// close all the channels | 		// close all the channels | ||||||
| 		// NOTE: close marks the router status as Stopped | 		// NOTE: close marks the router status as Stopped | ||||||
| 		r.close() | 		r.close() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user