1
1
//! Handle process life-time and message passing for proc-macro client
2
2
3
3
use std:: {
4
- io:: { self , BufRead , BufReader , Write } ,
4
+ io:: { self , BufRead , BufReader , Read , Write } ,
5
5
process:: { Child , ChildStdin , ChildStdout , Command , Stdio } ,
6
+ sync:: Arc ,
6
7
} ;
7
8
8
9
use paths:: { AbsPath , AbsPathBuf } ;
@@ -15,9 +16,11 @@ use crate::{
15
16
16
17
#[ derive( Debug ) ]
17
18
pub ( crate ) struct ProcMacroProcessSrv {
18
- _process : Process ,
19
+ process : Process ,
19
20
stdin : ChildStdin ,
20
21
stdout : BufReader < ChildStdout > ,
22
+ /// Populated when the server exits.
23
+ server_exited : Option < ServerError > ,
21
24
version : u32 ,
22
25
mode : SpanMode ,
23
26
}
@@ -29,9 +32,10 @@ impl ProcMacroProcessSrv {
29
32
let ( stdin, stdout) = process. stdio ( ) . expect ( "couldn't access child stdio" ) ;
30
33
31
34
io:: Result :: Ok ( ProcMacroProcessSrv {
32
- _process : process,
35
+ process,
33
36
stdin,
34
37
stdout,
38
+ server_exited : None ,
35
39
version : 0 ,
36
40
mode : SpanMode :: Id ,
37
41
} )
@@ -105,8 +109,35 @@ impl ProcMacroProcessSrv {
105
109
}
106
110
107
111
pub ( crate ) fn send_task ( & mut self , req : Request ) -> Result < Response , ServerError > {
112
+ if let Some ( server_error) = & self . server_exited {
113
+ return Err ( server_error. clone ( ) ) ;
114
+ }
115
+
108
116
let mut buf = String :: new ( ) ;
109
- send_request ( & mut self . stdin , & mut self . stdout , req, & mut buf)
117
+ send_request ( & mut self . stdin , & mut self . stdout , req, & mut buf) . map_err ( |e| {
118
+ if e. io . as_ref ( ) . map ( |it| it. kind ( ) ) == Some ( io:: ErrorKind :: BrokenPipe ) {
119
+ match self . process . child . try_wait ( ) {
120
+ Ok ( None ) => e,
121
+ Ok ( Some ( status) ) => {
122
+ let mut msg = String :: new ( ) ;
123
+ if !status. success ( ) {
124
+ if let Some ( stderr) = self . process . child . stderr . as_mut ( ) {
125
+ _ = stderr. read_to_string ( & mut msg) ;
126
+ }
127
+ }
128
+ let server_error = ServerError {
129
+ message : format ! ( "server exited with {status}: {msg}" ) ,
130
+ io : None ,
131
+ } ;
132
+ self . server_exited = Some ( server_error. clone ( ) ) ;
133
+ server_error
134
+ }
135
+ Err ( _) => e,
136
+ }
137
+ } else {
138
+ e
139
+ }
140
+ } )
110
141
}
111
142
}
112
143
@@ -145,9 +176,13 @@ fn send_request(
145
176
req : Request ,
146
177
buf : & mut String ,
147
178
) -> Result < Response , ServerError > {
148
- req. write ( & mut writer)
149
- . map_err ( |err| ServerError { message : "failed to write request" . into ( ) , io : Some ( err) } ) ?;
150
- let res = Response :: read ( & mut reader, buf)
151
- . map_err ( |err| ServerError { message : "failed to read response" . into ( ) , io : Some ( err) } ) ?;
179
+ req. write ( & mut writer) . map_err ( |err| ServerError {
180
+ message : "failed to write request" . into ( ) ,
181
+ io : Some ( Arc :: new ( err) ) ,
182
+ } ) ?;
183
+ let res = Response :: read ( & mut reader, buf) . map_err ( |err| ServerError {
184
+ message : "failed to read response" . into ( ) ,
185
+ io : Some ( Arc :: new ( err) ) ,
186
+ } ) ?;
152
187
res. ok_or_else ( || ServerError { message : "server exited" . into ( ) , io : None } )
153
188
}
0 commit comments