@@ -19,9 +19,9 @@ package rpc
19
19
import (
20
20
"context"
21
21
"io"
22
+ "sync"
22
23
"sync/atomic"
23
24
24
- mapset "github.com/deckarep/golang-set/v2"
25
25
"github.com/ethereum/go-ethereum/log"
26
26
)
27
27
@@ -45,13 +45,19 @@ const (
45
45
type Server struct {
46
46
services serviceRegistry
47
47
idgen func () ID
48
- run int32
49
- codecs mapset.Set [* ServerCodec ]
48
+
49
+ mutex sync.Mutex
50
+ codecs map [ServerCodec ]struct {}
51
+ run int32
50
52
}
51
53
52
54
// NewServer creates a new server instance with no registered handlers.
53
55
func NewServer () * Server {
54
- server := & Server {idgen : randomIDGenerator (), codecs : mapset .NewSet [* ServerCodec ](), run : 1 }
56
+ server := & Server {
57
+ idgen : randomIDGenerator (),
58
+ codecs : make (map [ServerCodec ]struct {}),
59
+ run : 1 ,
60
+ }
55
61
// Register the default service providing meta information about the RPC service such
56
62
// as the services and methods it offers.
57
63
rpcService := & RPCService {server }
@@ -75,20 +81,34 @@ func (s *Server) RegisterName(name string, receiver interface{}) error {
75
81
func (s * Server ) ServeCodec (codec ServerCodec , options CodecOption ) {
76
82
defer codec .close ()
77
83
78
- // Don't serve if server is stopped.
79
- if atomic .LoadInt32 (& s .run ) == 0 {
84
+ if ! s .trackCodec (codec ) {
80
85
return
81
86
}
82
-
83
- // Add the codec to the set so it can be closed by Stop.
84
- s .codecs .Add (& codec )
85
- defer s .codecs .Remove (& codec )
87
+ defer s .untrackCodec (codec )
86
88
87
89
c := initClient (codec , s .idgen , & s .services )
88
90
<- codec .closed ()
89
91
c .Close ()
90
92
}
91
93
94
+ func (s * Server ) trackCodec (codec ServerCodec ) bool {
95
+ s .mutex .Lock ()
96
+ defer s .mutex .Unlock ()
97
+
98
+ if atomic .LoadInt32 (& s .run ) == 0 {
99
+ return false // Don't serve if server is stopped.
100
+ }
101
+ s .codecs [codec ] = struct {}{}
102
+ return true
103
+ }
104
+
105
+ func (s * Server ) untrackCodec (codec ServerCodec ) {
106
+ s .mutex .Lock ()
107
+ defer s .mutex .Unlock ()
108
+
109
+ delete (s .codecs , codec )
110
+ }
111
+
92
112
// serveSingleRequest reads and processes a single RPC request from the given codec. This
93
113
// is used to serve HTTP connections. Subscriptions and reverse calls are not allowed in
94
114
// this mode.
@@ -120,12 +140,14 @@ func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) {
120
140
// requests to finish, then closes all codecs which will cancel pending requests and
121
141
// subscriptions.
122
142
func (s * Server ) Stop () {
143
+ s .mutex .Lock ()
144
+ defer s .mutex .Unlock ()
145
+
123
146
if atomic .CompareAndSwapInt32 (& s .run , 1 , 0 ) {
124
147
log .Debug ("RPC server shutting down" )
125
- s .codecs .Each (func (c * ServerCodec ) bool {
126
- (* c ).close ()
127
- return true
128
- })
148
+ for codec := range s .codecs {
149
+ codec .close ()
150
+ }
129
151
}
130
152
}
131
153
0 commit comments