Jelajahi Sumber

fix(db): correct unsafe RLock order (fixes #9906) (#9910)

Marshal() was called with the read lock held, and in turn called
Created() which also takes the read lock. This is fine by itself, but
there is a risk of deadlock if another call to lock the mutex happens
concurrently, as the lock call will block the inner rlock and the outer
rlock can never become unlocked.

It's an easy fix as marshalling is guaranteed to be called with a read
lock and does not need to call any methods that read lock themselves.
Jakob Borg 1 tahun lalu
induk
melakukan
d324b2ac86
1 mengubah file dengan 5 tambahan dan 4 penghapusan
  1. 5 4
      lib/db/meta.go

+ 5 - 4
lib/db/meta.go

@@ -76,11 +76,12 @@ func (m *metadataTracker) Unmarshal(bs []byte) error {
 	return nil
 	return nil
 }
 }
 
 
-// Marshal returns the protobuf representation of the metadataTracker
-func (m *metadataTracker) Marshal() ([]byte, error) {
+// protoMarshal returns the protobuf representation of the metadataTracker.
+// Must be called with the read lock held.
+func (m *metadataTracker) protoMarshal() ([]byte, error) {
 	dbc := &dbproto.CountsSet{
 	dbc := &dbproto.CountsSet{
 		Counts:  make([]*dbproto.Counts, len(m.counts.Counts)),
 		Counts:  make([]*dbproto.Counts, len(m.counts.Counts)),
-		Created: m.Created().UnixNano(),
+		Created: m.counts.Created,
 	}
 	}
 	for i, c := range m.counts.Counts {
 	for i, c := range m.counts.Counts {
 		dbc.Counts[i] = c.toWire()
 		dbc.Counts[i] = c.toWire()
@@ -109,7 +110,7 @@ func (m *metadataTracker) toDB(t backend.WriteTransaction, folder []byte) error
 		return nil
 		return nil
 	}
 	}
 
 
-	bs, err := m.Marshal()
+	bs, err := m.protoMarshal()
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}