14
14
15
15
//! Sync client of ttrpc.
16
16
17
- use nix:: sys:: socket:: * ;
18
- use nix:: unistd:: close;
17
+
19
18
use std:: collections:: HashMap ;
20
19
use std:: os:: unix:: io:: RawFd ;
21
20
use std:: sync:: mpsc;
22
21
use std:: sync:: { Arc , Mutex } ;
23
- use std:: { io , thread} ;
22
+ use std:: { thread} ;
24
23
25
- #[ cfg( target_os = "macos" ) ]
26
- use crate :: common:: set_fd_close_exec;
27
- use crate :: common:: { client_connect, SOCK_CLOEXEC } ;
28
24
use crate :: error:: { Error , Result } ;
25
+ use crate :: sync:: sys:: { ClientConnection } ;
29
26
use crate :: proto:: { Code , Codec , MessageHeader , Request , Response , MESSAGE_TYPE_RESPONSE } ;
30
27
use crate :: sync:: channel:: { read_message, write_message} ;
31
28
use std:: time:: Duration ;
@@ -36,38 +33,36 @@ type Receiver = mpsc::Receiver<(Vec<u8>, mpsc::SyncSender<Result<Vec<u8>>>)>;
36
33
/// A ttrpc Client (sync).
37
34
#[ derive( Clone ) ]
38
35
pub struct Client {
39
- _fd : RawFd ,
36
+ _fd : Arc < ClientConnection > ,
40
37
sender_tx : Sender ,
41
- _client_close : Arc < ClientClose > ,
42
38
}
43
39
44
40
impl Client {
45
41
pub fn connect ( sockaddr : & str ) -> Result < Client > {
46
- let fd = unsafe { client_connect ( sockaddr) ? } ;
47
- Ok ( Self :: new ( fd) )
42
+ let conn = ClientConnection :: client_connect ( sockaddr) ?;
43
+
44
+ Ok ( Self :: new_client ( conn) )
48
45
}
49
46
50
47
/// Initialize a new [`Client`] from raw file descriptor.
51
48
pub fn new ( fd : RawFd ) -> Client {
52
- let ( sender_tx , rx ) : ( Sender , Receiver ) = mpsc :: channel ( ) ;
49
+ let conn = ClientConnection :: new ( fd ) ;
53
50
54
- let ( recver_fd , close_fd ) =
55
- socketpair ( AddressFamily :: Unix , SockType :: Stream , None , SOCK_CLOEXEC ) . unwrap ( ) ;
51
+ Self :: new_client ( conn )
52
+ }
56
53
57
- // MacOS doesn't support descriptor creation with SOCK_CLOEXEC automically,
58
- // so there is a chance of leak if fork + exec happens in between of these calls.
59
- #[ cfg( target_os = "macos" ) ]
60
- {
61
- set_fd_close_exec ( recver_fd) . unwrap ( ) ;
62
- set_fd_close_exec ( close_fd) . unwrap ( ) ;
63
- }
54
+ fn new_client ( pipe_client : ClientConnection ) -> Client {
55
+ let client = Arc :: new ( pipe_client) ;
56
+
64
57
65
- let client_close = Arc :: new ( ClientClose { fd , close_fd } ) ;
58
+ let ( sender_tx , rx ) : ( Sender , Receiver ) = mpsc :: channel ( ) ;
66
59
60
+
67
61
let recver_map_orig = Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ;
68
62
69
63
//Sender
70
64
let recver_map = recver_map_orig. clone ( ) ;
65
+ let sender_client = client. clone ( ) ;
71
66
thread:: spawn ( move || {
72
67
let mut stream_id: u32 = 1 ;
73
68
for ( buf, recver_tx) in rx. iter ( ) {
@@ -80,7 +75,8 @@ impl Client {
80
75
}
81
76
let mut mh = MessageHeader :: new_request ( 0 , buf. len ( ) as u32 ) ;
82
77
mh. set_stream_id ( current_stream_id) ;
83
- if let Err ( e) = write_message ( fd, mh, buf) {
78
+ let c = sender_client. get_pipe_connection ( ) ;
79
+ if let Err ( e) = write_message ( & c, mh, buf) {
84
80
//Remove current_stream_id and recver_tx to recver_map
85
81
{
86
82
let mut map = recver_map. lock ( ) . unwrap ( ) ;
@@ -95,53 +91,28 @@ impl Client {
95
91
} ) ;
96
92
97
93
//Recver
94
+ let reciever_client = client. clone ( ) ;
98
95
thread:: spawn ( move || {
99
- let mut pollers = vec ! [
100
- libc:: pollfd {
101
- fd: recver_fd,
102
- events: libc:: POLLIN ,
103
- revents: 0 ,
104
- } ,
105
- libc:: pollfd {
106
- fd,
107
- events: libc:: POLLIN ,
108
- revents: 0 ,
109
- } ,
110
- ] ;
96
+
111
97
112
98
loop {
113
- let returned = unsafe {
114
- let pollers: & mut [ libc:: pollfd ] = & mut pollers;
115
- libc:: poll (
116
- pollers as * mut _ as * mut libc:: pollfd ,
117
- pollers. len ( ) as _ ,
118
- -1 ,
119
- )
120
- } ;
121
-
122
- if returned == -1 {
123
- let err = io:: Error :: last_os_error ( ) ;
124
- if err. raw_os_error ( ) == Some ( libc:: EINTR ) {
99
+
100
+ match reciever_client. ready ( ) {
101
+ Ok ( None ) => {
125
102
continue ;
126
103
}
127
-
128
- error ! ( "fatal error in process reaper:{}" , err) ;
129
- break ;
130
- } else if returned < 1 {
131
- continue ;
132
- }
133
-
134
- if pollers[ 0 ] . revents != 0 {
135
- break ;
136
- }
137
-
138
- if pollers[ pollers. len ( ) - 1 ] . revents == 0 {
139
- continue ;
104
+ Ok ( _) => { }
105
+ Err ( e) => {
106
+ error ! ( "pipeConnection ready error {:?}" , e) ;
107
+ break ;
108
+ }
140
109
}
141
-
142
110
let mh;
143
111
let buf;
144
- match read_message ( fd) {
112
+
113
+ let pipe_connection = reciever_client. get_pipe_connection ( ) ;
114
+
115
+ match read_message ( & pipe_connection) {
145
116
Ok ( ( x, y) ) => {
146
117
mh = x;
147
118
buf = y;
@@ -190,20 +161,18 @@ impl Client {
190
161
map. remove ( & mh. stream_id ) ;
191
162
}
192
163
193
- let _ = close ( recver_fd ) . map_err ( |e| {
164
+ let _ = reciever_client . close_receiver ( ) . map_err ( |e| {
194
165
warn ! (
195
- "failed to close recver_fd: {} with error: {:?}" ,
196
- recver_fd, e
166
+ "failed to close with error: {:?}" , e
197
167
)
198
168
} ) ;
199
169
200
170
trace ! ( "Recver quit" ) ;
201
171
} ) ;
202
172
203
173
Client {
204
- _fd : fd ,
174
+ _fd : client ,
205
175
sender_tx,
206
- _client_close : client_close,
207
176
}
208
177
}
209
178
pub fn request ( & self , req : Request ) -> Result < Response > {
@@ -239,15 +208,9 @@ impl Client {
239
208
}
240
209
}
241
210
242
- struct ClientClose {
243
- fd : RawFd ,
244
- close_fd : RawFd ,
245
- }
246
-
247
- impl Drop for ClientClose {
211
+ impl Drop for ClientConnection {
248
212
fn drop ( & mut self ) {
249
- close ( self . close_fd ) . unwrap ( ) ;
250
- close ( self . fd ) . unwrap ( ) ;
251
- trace ! ( "All client is droped" ) ;
213
+ self . close ( ) . unwrap ( ) ;
214
+ trace ! ( "All client is dropped" ) ;
252
215
}
253
216
}
0 commit comments