Fix ListenBucketNotification deadlock (#5028)

Previously ListenBucketNotificationHandler could deadlock with
PutObjectHandler's eventNotify call when a client closes its
connection. This change removes the cyclic dependency between the
channel and map of ARN to channels by using a separate done channel to
signal that the client has quit.
This commit is contained in:
Krishnan Parthasarathi
2017-11-16 18:56:06 +00:00
committed by Dee Koder
parent 5a2bdf6959
commit 67f66c40c1
5 changed files with 178 additions and 106 deletions
+5 -5
View File
@@ -60,7 +60,7 @@ type internalNotifier struct {
// Connected listeners is a map of listener ARNs to channels
// on which the ListenBucket API handler go routine is waiting
// for events to send to a client.
connectedListeners map[string]chan []NotificationEvent
connectedListeners map[string]*listenChan
rwMutex *sync.RWMutex
}
@@ -206,7 +206,7 @@ func (en eventNotifier) GetInternalTarget(arn string) *listenerLogger {
}
// Set a new sns target for an input sns ARN.
func (en *eventNotifier) AddListenerChan(snsARN string, listenerCh chan []NotificationEvent) error {
func (en *eventNotifier) AddListenerChan(snsARN string, listenerCh *listenChan) error {
if listenerCh == nil {
return errInvalidArgument
}
@@ -229,9 +229,9 @@ func (en *eventNotifier) SendListenerEvent(arn string, event []NotificationEvent
en.internal.rwMutex.Lock()
defer en.internal.rwMutex.Unlock()
ch, ok := en.internal.connectedListeners[arn]
listenChan, ok := en.internal.connectedListeners[arn]
if ok {
ch <- event
listenChan.sendNotificationEvent(event)
}
// If the channel is not present we ignore the event.
return nil
@@ -833,7 +833,7 @@ func initEventNotifier(objAPI ObjectLayer) error {
rwMutex: &sync.RWMutex{},
targets: listenTargets,
listenerConfigs: lConfigs,
connectedListeners: make(map[string]chan []NotificationEvent),
connectedListeners: make(map[string]*listenChan),
},
}