Browse Source

Improve memory safety with `defer` for event cleanup across handlers, optimize conditional logging, and bump version to `v0.4.3`.

main
mleku 4 months ago
parent
commit
2dd119401b
No known key found for this signature in database
  1. 85
      app/handle-req.go
  2. 26
      pkg/database/export.go
  3. 3
      pkg/encoders/event/binary_test.go
  4. 2
      pkg/version/version

85
app/handle-req.go

@ -114,33 +114,56 @@ func (l *Listener) HandleReq(msg []byte) (err error) {
continue continue
} }
} }
// Use a separate context for QueryEvents to prevent cancellation issues // Use a separate context for QueryEvents to prevent cancellation issues
queryCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) queryCtx, cancel := context.WithTimeout(
defer cancel() context.Background(), 30*time.Second,
log.T.F("HandleReq: About to QueryEvents for %s, main context done: %v", l.remote, l.ctx.Err() != nil) )
if events, err = l.QueryEvents(queryCtx, f); chk.E(err) { defer cancel()
if errors.Is(err, badger.ErrDBClosed) { log.T.F(
return "HandleReq: About to QueryEvents for %s, main context done: %v",
} l.remote, l.ctx.Err() != nil,
log.T.F("HandleReq: QueryEvents error for %s: %v", l.remote, err) )
err = nil if events, err = l.QueryEvents(queryCtx, f); chk.E(err) {
} if errors.Is(err, badger.ErrDBClosed) {
log.T.F("HandleReq: QueryEvents completed for %s, found %d events", l.remote, len(events)) return
}
log.T.F("HandleReq: QueryEvents error for %s: %v", l.remote, err)
err = nil
}
defer func() {
for _, ev := range events {
ev.Free()
}
}()
log.T.F(
"HandleReq: QueryEvents completed for %s, found %d events",
l.remote, len(events),
)
} }
var tmp event.S var tmp event.S
privCheck: privCheck:
for _, ev := range events { for _, ev := range events {
if kind.IsPrivileged(ev.Kind) && if kind.IsPrivileged(ev.Kind) &&
accessLevel != "admin" { // admins can see all events accessLevel != "admin" { // admins can see all events
log.I.F("checking privileged event %s", ev.ID) log.T.C(
func() string {
return fmt.Sprintf(
"checking privileged event %0x", ev.ID,
)
},
)
pk := l.authedPubkey.Load() pk := l.authedPubkey.Load()
if pk == nil { if pk == nil {
continue continue
} }
if utils.FastEqual(ev.Pubkey, pk) { if utils.FastEqual(ev.Pubkey, pk) {
log.I.F( log.T.C(
"privileged event %s is for logged in pubkey %0x", ev.ID, func() string {
pk, return fmt.Sprintf(
"privileged event %s is for logged in pubkey %0x",
ev.ID, pk,
)
},
) )
tmp = append(tmp, ev) tmp = append(tmp, ev)
continue continue
@ -152,17 +175,25 @@ privCheck:
continue continue
} }
if utils.FastEqual(pt, pk) { if utils.FastEqual(pt, pk) {
log.I.F( log.T.C(
"privileged event %s is for logged in pubkey %0x", func() string {
ev.ID, pk, return fmt.Sprintf(
"privileged event %s is for logged in pubkey %0x",
ev.ID, pk,
)
},
) )
tmp = append(tmp, ev) tmp = append(tmp, ev)
continue privCheck continue privCheck
} }
} }
log.W.F( log.T.C(
"privileged event %s does not contain the logged in pubkey %0x", func() string {
ev.ID, pk, return fmt.Sprintf(
"privileged event %s does not contain the logged in pubkey %0x",
ev.ID, pk,
)
},
) )
} else { } else {
tmp = append(tmp, ev) tmp = append(tmp, ev)
@ -171,9 +202,13 @@ privCheck:
events = tmp events = tmp
seen := make(map[string]struct{}) seen := make(map[string]struct{})
for _, ev := range events { for _, ev := range events {
log.T.F( log.D.C(
"REQ %s: sending EVENT id=%s kind=%d", env.Subscription, func() string {
hex.Enc(ev.ID), ev.Kind, return fmt.Sprintf(
"REQ %s: sending EVENT id=%s kind=%d", env.Subscription,
hex.Enc(ev.ID), ev.Kind,
)
},
) )
log.T.C( log.T.C(
func() string { func() string {

26
pkg/database/export.go

@ -43,14 +43,16 @@ func (d *D) Export(c context.Context, w io.Writer, pubkeys ...[]byte) {
continue continue
} }
// Serialize the event to JSON and write it to the output // Serialize the event to JSON and write it to the output
defer func(ev *event.E) {
ev.Free()
evBuf.Reset()
}(ev)
if _, err = w.Write(ev.Serialize()); chk.E(err) { if _, err = w.Write(ev.Serialize()); chk.E(err) {
return return
} }
if _, err = w.Write([]byte{'\n'}); chk.E(err) { if _, err = w.Write([]byte{'\n'}); chk.E(err) {
return return
} }
ev.Free()
evBuf.Reset()
} }
return return
}, },
@ -87,15 +89,17 @@ func (d *D) Export(c context.Context, w io.Writer, pubkeys ...[]byte) {
if err = ev.UnmarshalBinary(evBuf); chk.E(err) { if err = ev.UnmarshalBinary(evBuf); chk.E(err) {
continue continue
} }
// Serialize the event to JSON and write it to the output // Serialize the event to JSON and write it to the output
if _, err = w.Write(ev.Serialize()); chk.E(err) { defer func(ev *event.E) {
continue ev.Free()
} evBuf.Reset()
if _, err = w.Write([]byte{'\n'}); chk.E(err) { }(ev)
continue if _, err = w.Write(ev.Serialize()); chk.E(err) {
} continue
ev.Free() }
evBuf.Reset() if _, err = w.Write([]byte{'\n'}); chk.E(err) {
continue
}
} }
return return
}, },

3
pkg/encoders/event/binary_test.go

@ -48,6 +48,9 @@ func TestTMarshalBinary_UnmarshalBinary(t *testing.T) {
// Marshal unmarshaled binary event back to JSON // Marshal unmarshaled binary event back to JSON
unmarshaledJSON := eb.Serialize() unmarshaledJSON := eb.Serialize()
defer func(ev *E) {
eb.Free()
}(eb)
// Compare the two JSON representations // Compare the two JSON representations
if !utils.FastEqual(b, unmarshaledJSON) { if !utils.FastEqual(b, unmarshaledJSON) {

2
pkg/version/version

@ -1 +1 @@
v0.4.2 v0.4.3
Loading…
Cancel
Save