13
13
// limitations under the License.
14
14
15
15
//! Sync server of ttrpc.
16
- //!
16
+ //!
17
17
18
18
#[ cfg( unix) ]
19
19
use std:: os:: unix:: io:: { AsRawFd , FromRawFd , RawFd } ;
@@ -23,16 +23,16 @@ use std::collections::HashMap;
23
23
use std:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ;
24
24
use std:: sync:: mpsc:: { channel, sync_channel, Receiver , Sender , SyncSender } ;
25
25
use std:: sync:: { Arc , Mutex } ;
26
+ use std:: thread;
26
27
use std:: thread:: JoinHandle ;
27
- use std:: { thread} ;
28
28
29
29
use super :: utils:: response_to_channel;
30
30
use crate :: context;
31
31
use crate :: error:: { get_status, Error , Result } ;
32
32
use crate :: proto:: { Code , MessageHeader , Request , Response , MESSAGE_TYPE_REQUEST } ;
33
33
use crate :: sync:: channel:: { read_message, write_message} ;
34
+ use crate :: sync:: sys:: { PipeConnection , PipeListener } ;
34
35
use crate :: { MethodHandler , TtrpcContext } ;
35
- use crate :: sync:: sys:: { PipeListener , PipeConnection } ;
36
36
37
37
// poll_queue will create WAIT_THREAD_COUNT_DEFAULT threads in begin.
38
38
// If wait thread count < WAIT_THREAD_COUNT_MIN, create number to WAIT_THREAD_COUNT_DEFAULT.
@@ -43,6 +43,8 @@ const DEFAULT_WAIT_THREAD_COUNT_MAX: usize = 5;
43
43
44
44
type MessageSender = Sender < ( MessageHeader , Vec < u8 > ) > ;
45
45
type MessageReceiver = Receiver < ( MessageHeader , Vec < u8 > ) > ;
46
+ type WorkloadSender = crossbeam:: channel:: Sender < ( MessageHeader , Vec < u8 > ) > ;
47
+ type WorkloadReceiver = crossbeam:: channel:: Receiver < ( MessageHeader , Vec < u8 > ) > ;
46
48
47
49
/// A ttrpc Server (sync).
48
50
pub struct Server {
@@ -64,7 +66,7 @@ struct Connection {
64
66
}
65
67
66
68
impl Connection {
67
- fn close ( & self ) {
69
+ fn close ( & self ) {
68
70
self . connection . close ( ) . unwrap_or ( ( ) ) ;
69
71
}
70
72
@@ -77,13 +79,14 @@ impl Connection {
77
79
}
78
80
79
81
struct ThreadS < ' a > {
80
- connection : & ' a Arc < PipeConnection > ,
81
- fdlock : & ' a Arc < Mutex < ( ) > > ,
82
+ connection : & ' a Arc < PipeConnection > ,
83
+ workload_rx : & ' a WorkloadReceiver ,
82
84
wtc : & ' a Arc < AtomicUsize > ,
83
85
quit : & ' a Arc < AtomicBool > ,
84
86
methods : & ' a Arc < HashMap < String , Box < dyn MethodHandler + Send + Sync > > > ,
85
87
res_tx : & ' a MessageSender ,
86
88
control_tx : & ' a SyncSender < ( ) > ,
89
+ cancel_rx : & ' a crossbeam:: channel:: Receiver < ( ) > ,
87
90
default : usize ,
88
91
min : usize ,
89
92
max : usize ,
@@ -92,12 +95,13 @@ struct ThreadS<'a> {
92
95
#[ allow( clippy:: too_many_arguments) ]
93
96
fn start_method_handler_thread (
94
97
connection : Arc < PipeConnection > ,
95
- fdlock : Arc < Mutex < ( ) > > ,
98
+ workload_rx : WorkloadReceiver ,
96
99
wtc : Arc < AtomicUsize > ,
97
100
quit : Arc < AtomicBool > ,
98
101
methods : Arc < HashMap < String , Box < dyn MethodHandler + Send + Sync > > > ,
99
102
res_tx : MessageSender ,
100
103
control_tx : SyncSender < ( ) > ,
104
+ cancel_rx : crossbeam:: channel:: Receiver < ( ) > ,
101
105
min : usize ,
102
106
max : usize ,
103
107
) {
@@ -109,18 +113,7 @@ fn start_method_handler_thread(
109
113
break ;
110
114
}
111
115
112
- let result;
113
- {
114
- let _guard = fdlock. lock ( ) . unwrap ( ) ;
115
- if quit. load ( Ordering :: SeqCst ) {
116
- // notify the connection dealing main thread to stop.
117
- control_tx
118
- . send ( ( ) )
119
- . unwrap_or_else ( |err| trace ! ( "Failed to send {:?}" , err) ) ;
120
- break ;
121
- }
122
- result = read_message ( & connection) ;
123
- }
116
+ let result = workload_rx. recv ( ) ;
124
117
125
118
if quit. load ( Ordering :: SeqCst ) {
126
119
// notify the connection dealing main thread to stop.
@@ -146,22 +139,18 @@ fn start_method_handler_thread(
146
139
buf = y;
147
140
}
148
141
Err ( x) => match x {
149
- Error :: Socket ( y ) => {
150
- trace ! ( "Socket error {}" , y ) ;
142
+ crossbeam :: channel :: RecvError => {
143
+ trace ! ( "workload_rx recv error" ) ;
151
144
quit. store ( true , Ordering :: SeqCst ) ;
152
- // the client connection would be closed and
145
+ // the workload tx would be dropped and
153
146
// the connection dealing main thread would
154
147
// have exited.
155
148
control_tx
156
149
. send ( ( ) )
157
150
. unwrap_or_else ( |err| trace ! ( "Failed to send {:?}" , err) ) ;
158
- trace ! ( "Socket error send control_tx" ) ;
151
+ trace ! ( "workload_rx recv error, send control_tx" ) ;
159
152
break ;
160
153
}
161
- _ => {
162
- trace ! ( "Others error {:?}" , x) ;
163
- continue ;
164
- }
165
154
} ,
166
155
}
167
156
@@ -211,6 +200,7 @@ fn start_method_handler_thread(
211
200
} ;
212
201
let ctx = TtrpcContext {
213
202
fd : connection. id ( ) ,
203
+ cancel_rx : cancel_rx. clone ( ) ,
214
204
mh,
215
205
res_tx : res_tx. clone ( ) ,
216
206
metadata : context:: from_pb ( & req. metadata ) ,
@@ -238,12 +228,13 @@ fn start_method_handler_threads(num: usize, ts: &ThreadS) {
238
228
}
239
229
start_method_handler_thread (
240
230
ts. connection . clone ( ) ,
241
- ts. fdlock . clone ( ) ,
231
+ ts. workload_rx . clone ( ) ,
242
232
ts. wtc . clone ( ) ,
243
233
ts. quit . clone ( ) ,
244
234
ts. methods . clone ( ) ,
245
235
ts. res_tx . clone ( ) ,
246
236
ts. control_tx . clone ( ) ,
237
+ ts. cancel_rx . clone ( ) ,
247
238
ts. min ,
248
239
ts. max ,
249
240
) ;
@@ -300,7 +291,7 @@ impl Server {
300
291
}
301
292
302
293
let listener = PipeListener :: new_from_fd ( fd) ?;
303
-
294
+
304
295
self . listeners . push ( Arc :: new ( listener) ) ;
305
296
306
297
Ok ( self )
@@ -339,8 +330,6 @@ impl Server {
339
330
340
331
self . listener_quit_flag . store ( false , Ordering :: SeqCst ) ;
341
332
342
-
343
-
344
333
let listener = self . listeners [ 0 ] . clone ( ) ;
345
334
let methods = self . methods . clone ( ) ;
346
335
let default = self . thread_count_default ;
@@ -383,15 +372,13 @@ impl Server {
383
372
let handler = thread:: Builder :: new ( )
384
373
. name ( "listener_loop" . into ( ) )
385
374
. spawn ( move || {
386
- loop {
375
+ loop {
387
376
trace ! ( "listening..." ) ;
388
377
let pipe_connection = match listener. accept ( & listener_quit_flag) {
389
378
Ok ( None ) => {
390
379
continue ;
391
380
}
392
- Ok ( Some ( conn) ) => {
393
- Arc :: new ( conn)
394
- }
381
+ Ok ( Some ( conn) ) => Arc :: new ( conn) ,
395
382
Err ( e) => {
396
383
error ! ( "listener accept got {:?}" , e) ;
397
384
break ;
@@ -425,16 +412,68 @@ impl Server {
425
412
trace ! ( "response thread quit" ) ;
426
413
} ) ;
427
414
428
- let pipe = pipe_connection_child. clone ( ) ;
429
415
let ( control_tx, control_rx) : ( SyncSender < ( ) > , Receiver < ( ) > ) =
430
416
sync_channel ( 0 ) ;
417
+
418
+ // start read message thread
419
+ let quit_reader = child_quit. clone ( ) ;
420
+ let pipe_reader = pipe_connection_child. clone ( ) ;
421
+ let ( workload_tx, workload_rx) : ( WorkloadSender , WorkloadReceiver ) =
422
+ crossbeam:: channel:: unbounded ( ) ;
423
+ let ( cancel_tx, cancel_rx) = crossbeam:: channel:: unbounded :: < ( ) > ( ) ;
424
+ let control_tx_reader = control_tx. clone ( ) ;
425
+ let reader = thread:: spawn ( move || {
426
+ while !quit_reader. load ( Ordering :: SeqCst ) {
427
+ let msg = read_message ( & pipe_reader) ;
428
+ match msg {
429
+ Ok ( ( x, y) ) => {
430
+ let res = workload_tx. send ( ( x, y) ) ;
431
+ match res {
432
+ Ok ( _) => { }
433
+ Err ( crossbeam:: channel:: SendError ( e) ) => {
434
+ error ! ( "Send workload error {:?}" , e) ;
435
+ quit_reader. store ( true , Ordering :: SeqCst ) ;
436
+ control_tx_reader. send ( ( ) ) . unwrap_or_else (
437
+ |err| trace ! ( "Failed to send {:?}" , err) ,
438
+ ) ;
439
+ break ;
440
+ }
441
+ }
442
+ }
443
+ Err ( x) => match x {
444
+ Error :: Socket ( y) => {
445
+ trace ! ( "Socket error {}" , y) ;
446
+ drop ( cancel_tx) ;
447
+ quit_reader. store ( true , Ordering :: SeqCst ) ;
448
+ // the client connection would be closed and
449
+ // the connection dealing main thread would
450
+ // have exited.
451
+ control_tx_reader. send ( ( ) ) . unwrap_or_else ( |err| {
452
+ trace ! ( "Failed to send {:?}" , err)
453
+ } ) ;
454
+ trace ! ( "Socket error send control_tx" ) ;
455
+ break ;
456
+ }
457
+ _ => {
458
+ trace ! ( "Other error {:?}" , x) ;
459
+ continue ;
460
+ }
461
+ } ,
462
+ }
463
+ }
464
+
465
+ trace ! ( "read message thread quit" ) ;
466
+ } ) ;
467
+
468
+ let pipe = pipe_connection_child. clone ( ) ;
431
469
let ts = ThreadS {
432
470
connection : & pipe,
433
- fdlock : & Arc :: new ( Mutex :: new ( ( ) ) ) ,
471
+ workload_rx : & workload_rx ,
434
472
wtc : & Arc :: new ( AtomicUsize :: new ( 0 ) ) ,
435
473
methods : & methods,
436
474
res_tx : & res_tx,
437
475
control_tx : & control_tx,
476
+ cancel_rx : & cancel_rx,
438
477
quit : & child_quit,
439
478
default,
440
479
min,
@@ -453,7 +492,9 @@ impl Server {
453
492
drop ( control_rx) ;
454
493
// drop the res_tx, thus the res_rx would get terminated notification.
455
494
drop ( res_tx) ;
495
+ drop ( workload_rx) ;
456
496
handler. join ( ) . unwrap_or ( ( ) ) ;
497
+ reader. join ( ) . unwrap_or ( ( ) ) ;
457
498
// client_handler should not close fd before exit
458
499
// , which prevent fd reuse issue.
459
500
reaper_tx_child. send ( pipe. id ( ) ) . unwrap ( ) ;
@@ -505,12 +546,10 @@ impl Server {
505
546
pub fn stop_listen ( mut self ) -> Self {
506
547
self . listener_quit_flag . store ( true , Ordering :: SeqCst ) ;
507
548
508
- self . listeners [ 0 ] . close ( ) . unwrap_or_else ( |e| {
509
- warn ! (
510
- "failed to close connection with error: {}" , e
511
- )
512
- } ) ;
513
-
549
+ self . listeners [ 0 ]
550
+ . close ( )
551
+ . unwrap_or_else ( |e| warn ! ( "failed to close connection with error: {}" , e) ) ;
552
+
514
553
info ! ( "close monitor" ) ;
515
554
if let Some ( handler) = self . handler . take ( ) {
516
555
handler. join ( ) . unwrap ( ) ;
0 commit comments