20735: Workaround nginx/glibc/docker issue.
[arvados.git] / services / keep-web / handler.go
index e9b497a0b1165f5327bc74e7970f69d34318cf6e..3af326a1ad451483da29bb6398624b508e0d1fe2 100644 (file)
@@ -37,8 +37,9 @@ type handler struct {
        Cluster   *arvados.Cluster
        setupOnce sync.Once
 
-       lockMtx sync.Mutex
-       lock    map[string]*sync.RWMutex
+       lockMtx    sync.Mutex
+       lock       map[string]*sync.RWMutex
+       lockTidied time.Time
 }
 
 var urlPDHDecoder = strings.NewReplacer(" ", "+", "-", "+")
@@ -410,16 +411,20 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
                        // collection id is outside scope of supplied
                        // token
                        tokenScopeProblem = true
+                       sess.Release()
                        continue
                } else if os.IsNotExist(err) {
                        // collection does not exist or is not
                        // readable using this token
+                       sess.Release()
                        continue
                } else if err != nil {
                        http.Error(w, err.Error(), http.StatusInternalServerError)
+                       sess.Release()
                        return
                }
                defer f.Close()
+               defer sess.Release()
 
                collectionDir, sessionFS, session, tokenUser = f, fs, sess, user
                break
@@ -958,6 +963,16 @@ var lockTidyInterval = time.Minute * 10
 func (h *handler) collectionLock(collectionID string, writing bool) sync.Locker {
        h.lockMtx.Lock()
        defer h.lockMtx.Unlock()
+       if time.Since(h.lockTidied) > lockTidyInterval {
+               // Periodically delete all locks that aren't in use.
+               h.lockTidied = time.Now()
+               for id, locker := range h.lock {
+                       if locker.TryLock() {
+                               locker.Unlock()
+                               delete(h.lock, id)
+                       }
+               }
+       }
        locker := h.lock[collectionID]
        if locker == nil {
                locker = new(sync.RWMutex)