2
2
3
3
use std:: {
4
4
io:: { self , BufRead , BufReader , Read , Write } ,
5
+ panic:: AssertUnwindSafe ,
5
6
process:: { Child , ChildStdin , ChildStdout , Command , Stdio } ,
6
- sync:: { Arc , Mutex } ,
7
+ sync:: { Arc , Mutex , OnceLock } ,
7
8
} ;
8
9
9
10
use paths:: AbsPath ;
@@ -22,15 +23,15 @@ pub(crate) struct ProcMacroProcessSrv {
22
23
state : Mutex < ProcessSrvState > ,
23
24
version : u32 ,
24
25
mode : SpanMode ,
26
+ /// Populated when the server exits.
27
+ exited : OnceLock < AssertUnwindSafe < ServerError > > ,
25
28
}
26
29
27
30
#[ derive( Debug ) ]
28
31
struct ProcessSrvState {
29
32
process : Process ,
30
33
stdin : ChildStdin ,
31
34
stdout : BufReader < ChildStdout > ,
32
- /// Populated when the server exits.
33
- server_exited : Option < ServerError > ,
34
35
}
35
36
36
37
impl ProcMacroProcessSrv {
@@ -44,9 +45,10 @@ impl ProcMacroProcessSrv {
44
45
let ( stdin, stdout) = process. stdio ( ) . expect ( "couldn't access child stdio" ) ;
45
46
46
47
io:: Result :: Ok ( ProcMacroProcessSrv {
47
- state : Mutex :: new ( ProcessSrvState { process, stdin, stdout, server_exited : None } ) ,
48
+ state : Mutex :: new ( ProcessSrvState { process, stdin, stdout } ) ,
48
49
version : 0 ,
49
50
mode : SpanMode :: Id ,
51
+ exited : OnceLock :: new ( ) ,
50
52
} )
51
53
} ;
52
54
let mut srv = create_srv ( true ) ?;
@@ -77,6 +79,10 @@ impl ProcMacroProcessSrv {
77
79
}
78
80
}
79
81
82
+ pub ( crate ) fn exited ( & self ) -> Option < & ServerError > {
83
+ self . exited . get ( ) . map ( |it| & it. 0 )
84
+ }
85
+
80
86
pub ( crate ) fn version ( & self ) -> u32 {
81
87
self . version
82
88
}
@@ -118,36 +124,52 @@ impl ProcMacroProcessSrv {
118
124
}
119
125
120
126
pub ( crate ) fn send_task ( & self , req : Request ) -> Result < Response , ServerError > {
121
- let state = & mut * self . state . lock ( ) . unwrap ( ) ;
122
- if let Some ( server_error) = & state. server_exited {
123
- return Err ( server_error. clone ( ) ) ;
127
+ if let Some ( server_error) = self . exited . get ( ) {
128
+ return Err ( server_error. 0 . clone ( ) ) ;
124
129
}
125
130
131
+ let state = & mut * self . state . lock ( ) . unwrap ( ) ;
126
132
let mut buf = String :: new ( ) ;
127
- send_request ( & mut state. stdin , & mut state. stdout , req, & mut buf) . map_err ( |e| {
128
- if e. io . as_ref ( ) . map ( |it| it. kind ( ) ) == Some ( io:: ErrorKind :: BrokenPipe ) {
129
- match state. process . child . try_wait ( ) {
130
- Ok ( None ) => e,
131
- Ok ( Some ( status) ) => {
132
- let mut msg = String :: new ( ) ;
133
- if !status. success ( ) {
134
- if let Some ( stderr) = state. process . child . stderr . as_mut ( ) {
135
- _ = stderr. read_to_string ( & mut msg) ;
133
+ send_request ( & mut state. stdin , & mut state. stdout , req, & mut buf)
134
+ . and_then ( |res| {
135
+ res. ok_or_else ( || {
136
+ let message = "proc-macro server did not respond with data" . to_owned ( ) ;
137
+ ServerError {
138
+ io : Some ( Arc :: new ( io:: Error :: new (
139
+ io:: ErrorKind :: BrokenPipe ,
140
+ message. clone ( ) ,
141
+ ) ) ) ,
142
+ message,
143
+ }
144
+ } )
145
+ } )
146
+ . map_err ( |e| {
147
+ if e. io . as_ref ( ) . map ( |it| it. kind ( ) ) == Some ( io:: ErrorKind :: BrokenPipe ) {
148
+ match state. process . child . try_wait ( ) {
149
+ Ok ( None ) | Err ( _) => e,
150
+ Ok ( Some ( status) ) => {
151
+ let mut msg = String :: new ( ) ;
152
+ if !status. success ( ) {
153
+ if let Some ( stderr) = state. process . child . stderr . as_mut ( ) {
154
+ _ = stderr. read_to_string ( & mut msg) ;
155
+ }
136
156
}
157
+ let server_error = ServerError {
158
+ message : format ! (
159
+ "proc-macro server exited with {status}{}{msg}" ,
160
+ if msg. is_empty( ) { "" } else { ": " }
161
+ ) ,
162
+ io : None ,
163
+ } ;
164
+ // `AssertUnwindSafe` is fine here, we already correct initialized
165
+ // server_error at this point.
166
+ self . exited . get_or_init ( || AssertUnwindSafe ( server_error) ) . 0 . clone ( )
137
167
}
138
- let server_error = ServerError {
139
- message : format ! ( "server exited with {status}: {msg}" ) ,
140
- io : None ,
141
- } ;
142
- state. server_exited = Some ( server_error. clone ( ) ) ;
143
- server_error
144
168
}
145
- Err ( _) => e,
169
+ } else {
170
+ e
146
171
}
147
- } else {
148
- e
149
- }
150
- } )
172
+ } )
151
173
}
152
174
}
153
175
@@ -201,7 +223,7 @@ fn send_request(
201
223
mut reader : & mut impl BufRead ,
202
224
req : Request ,
203
225
buf : & mut String ,
204
- ) -> Result < Response , ServerError > {
226
+ ) -> Result < Option < Response > , ServerError > {
205
227
req. write ( write_json, & mut writer) . map_err ( |err| ServerError {
206
228
message : "failed to write request" . into ( ) ,
207
229
io : Some ( Arc :: new ( err) ) ,
@@ -210,5 +232,5 @@ fn send_request(
210
232
message : "failed to read response" . into ( ) ,
211
233
io : Some ( Arc :: new ( err) ) ,
212
234
} ) ?;
213
- res . ok_or_else ( || ServerError { message : "server exited" . into ( ) , io : None } )
235
+ Ok ( res )
214
236
}
0 commit comments