Skip to content

Commit 3c0147b

Browse files
xaionaro@dx.centerxaionaro@dx.center
authored andcommitted
fix: use deferred mutex unlocks for panic safety
Convert HandleStore.Put and Get to use defer mu.Unlock(). Wrap sendMu-protected stream.Send calls in closures with deferred unlock to prevent mutex leaks if Send panics. HandleStore.Release intentionally unlocks before DeleteGlobalRef to avoid holding the mutex during JNI work — left as-is with comment.
1 parent 23f99cb commit 3c0147b

2 files changed

Lines changed: 20 additions & 16 deletions

File tree

grpc/server/jni_raw/proxy_stream.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,12 @@ func (s *Server) Proxy(stream pb.JNIService_ProxyServer) error {
114114
pendingMu.Unlock()
115115
}
116116

117-
sendMu.Lock()
118-
sendErr := stream.Send(event)
119-
sendMu.Unlock()
117+
var sendErr error
118+
func() {
119+
sendMu.Lock()
120+
defer sendMu.Unlock()
121+
sendErr = stream.Send(event)
122+
}()
120123
if sendErr != nil {
121124
if ch != nil {
122125
pendingMu.Lock()
@@ -311,15 +314,17 @@ func (s *Server) Proxy(stream pb.JNIService_ProxyServer) error {
311314
// 7. proxyHandle was set inside the VM.Do callbacks above (local JNI
312315
// refs are thread-local — must be stored before VM.Do returns).
313316

314-
sendMu.Lock()
315-
err = stream.Send(&pb.ProxyServerMessage{
316-
Msg: &pb.ProxyServerMessage_Created{
317-
Created: &pb.CreateProxyResponse{
318-
ProxyHandle: proxyHandle,
317+
err = func() error {
318+
sendMu.Lock()
319+
defer sendMu.Unlock()
320+
return stream.Send(&pb.ProxyServerMessage{
321+
Msg: &pb.ProxyServerMessage_Created{
322+
Created: &pb.CreateProxyResponse{
323+
ProxyHandle: proxyHandle,
324+
},
319325
},
320-
},
321-
})
322-
sendMu.Unlock()
326+
})
327+
}()
323328
if err != nil {
324329
return err
325330
}

handlestore/handlestore.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ func (s *HandleStore) Put(env *jni.Env, obj *jni.Object) int64 {
3939
globalRef := env.NewGlobalRef(obj)
4040
id := s.nextID.Add(1)
4141
s.mu.Lock()
42+
defer s.mu.Unlock()
4243
s.objects[id] = globalRef
43-
s.mu.Unlock()
4444
return id
4545
}
4646

@@ -51,9 +51,8 @@ func (s *HandleStore) Get(handle int64) *jni.Object {
5151
return nil
5252
}
5353
s.mu.RLock()
54-
obj := s.objects[handle]
55-
s.mu.RUnlock()
56-
return obj
54+
defer s.mu.RUnlock()
55+
return s.objects[handle]
5756
}
5857

5958
// Release deletes the JNI global reference for the given handle and removes
@@ -68,7 +67,7 @@ func (s *HandleStore) Release(env *jni.Env, handle int64) {
6867
if ok {
6968
delete(s.objects, handle)
7069
}
71-
s.mu.Unlock()
70+
s.mu.Unlock() // Unlock before JNI call to avoid holding the mutex during DeleteGlobalRef.
7271
if ok {
7372
env.DeleteGlobalRef(obj)
7473
}

0 commit comments

Comments
 (0)