@@ -82,7 +82,8 @@ type wsConn struct {
8282 inflightLk sync.Mutex
8383
8484 // chanHandlers is a map of client-side channel handlers
85- chanHandlers map [uint64 ]func (m []byte , ok bool )
85+ chanHandlersLk sync.Mutex
86+ chanHandlers map [uint64 ]* chanHandler
8687
8788 // ////
8889 // Server related
@@ -99,6 +100,13 @@ type wsConn struct {
99100 registerCh chan outChanReg
100101}
101102
103+ type chanHandler struct {
104+ // take inside chanHandlersLk
105+ lk sync.Mutex
106+
107+ cb func (m []byte , ok bool )
108+ }
109+
102110// //
103111// WebSocket Message utils //
104112// //
@@ -367,13 +375,20 @@ func (c *wsConn) handleChanMessage(frame frame) {
367375 return
368376 }
369377
378+ c .chanHandlersLk .Lock ()
370379 hnd , ok := c .chanHandlers [chid ]
371380 if ! ok {
381+ c .chanHandlersLk .Unlock ()
372382 log .Errorf ("xrpc.ch.val: handler %d not found" , chid )
373383 return
374384 }
375385
376- hnd (params [1 ].data , true )
386+ hnd .lk .Lock ()
387+ defer hnd .lk .Unlock ()
388+
389+ c .chanHandlersLk .Unlock ()
390+
391+ hnd .cb (params [1 ].data , true )
377392}
378393
379394func (c * wsConn ) handleChanClose (frame frame ) {
@@ -389,15 +404,22 @@ func (c *wsConn) handleChanClose(frame frame) {
389404 return
390405 }
391406
407+ c .chanHandlersLk .Lock ()
392408 hnd , ok := c .chanHandlers [chid ]
393409 if ! ok {
410+ c .chanHandlersLk .Unlock ()
394411 log .Errorf ("xrpc.ch.val: handler %d not found" , chid )
395412 return
396413 }
397414
415+ hnd .lk .Lock ()
416+ defer hnd .lk .Unlock ()
417+
398418 delete (c .chanHandlers , chid )
399419
400- hnd (nil , false )
420+ c .chanHandlersLk .Unlock ()
421+
422+ hnd .cb (nil , false )
401423}
402424
403425func (c * wsConn ) handleResponse (frame frame ) {
@@ -417,8 +439,12 @@ func (c *wsConn) handleResponse(frame frame) {
417439 return
418440 }
419441
420- var chanCtx context.Context
421- chanCtx , c .chanHandlers [chid ] = req .retCh ()
442+ chanCtx , chHnd := req .retCh ()
443+
444+ c .chanHandlersLk .Lock ()
445+ c .chanHandlers [chid ] = & chanHandler {cb : chHnd }
446+ c .chanHandlersLk .Unlock ()
447+
422448 go c .handleCtxAsync (chanCtx , frame .ID )
423449 }
424450
@@ -517,16 +543,28 @@ func (c *wsConn) closeInFlight() {
517543 for _ , cancel := range c .handling {
518544 cancel ()
519545 }
546+ c .handling = map [interface {}]context.CancelFunc {}
520547 c .handlingLk .Unlock ()
521548
522- c .handling = map [interface {}]context.CancelFunc {}
523549}
524550
525551func (c * wsConn ) closeChans () {
552+ c .chanHandlersLk .Lock ()
553+ defer c .chanHandlersLk .Unlock ()
554+
526555 for chid := range c .chanHandlers {
527556 hnd := c .chanHandlers [chid ]
557+
558+ hnd .lk .Lock ()
559+
528560 delete (c .chanHandlers , chid )
529- hnd (nil , false )
561+
562+ c .chanHandlersLk .Unlock ()
563+
564+ hnd .cb (nil , false )
565+
566+ hnd .lk .Unlock ()
567+ c .chanHandlersLk .Lock ()
530568 }
531569}
532570
@@ -679,7 +717,7 @@ func (c *wsConn) handleWsConn(ctx context.Context) {
679717 c .frameExecQueue = make (chan []byte , maxQueuedFrames )
680718 c .inflight = map [interface {}]clientRequest {}
681719 c .handling = map [interface {}]context.CancelFunc {}
682- c .chanHandlers = map [uint64 ]func ( m [] byte , ok bool ) {}
720+ c .chanHandlers = map [uint64 ]* chanHandler {}
683721 c .pongs = make (chan struct {}, 1 )
684722
685723 c .registerCh = make (chan outChanReg )
0 commit comments