3
3
use std:: {
4
4
convert:: { TryFrom , TryInto } ,
5
5
ffi:: { OsStr , OsString } ,
6
+ fmt,
6
7
io:: { self , BufRead , BufReader , Write } ,
7
8
path:: { Path , PathBuf } ,
8
- process:: { Child , Command , Stdio } ,
9
- sync:: { Arc , Weak } ,
9
+ process:: { Child , ChildStdin , ChildStdout , Command , Stdio } ,
10
+ sync:: Mutex ,
10
11
} ;
11
12
12
- use crossbeam_channel:: { bounded, Receiver , Sender } ;
13
13
use stdx:: JodChild ;
14
14
15
15
use crate :: {
16
16
msg:: { ErrorCode , Message , Request , Response , ResponseError } ,
17
17
rpc:: { ListMacrosResult , ListMacrosTask , ProcMacroKind } ,
18
18
} ;
19
19
20
- #[ derive( Debug , Default ) ]
21
20
pub ( crate ) struct ProcMacroProcessSrv {
22
- inner : Weak < Sender < Task > > ,
21
+ process : Mutex < Process > ,
22
+ stdio : Mutex < ( ChildStdin , BufReader < ChildStdout > ) > ,
23
23
}
24
24
25
- #[ derive( Debug ) ]
26
- pub ( crate ) struct ProcMacroProcessThread {
27
- // XXX: drop order is significant
28
- sender : Arc < Sender < Task > > ,
29
- handle : jod_thread:: JoinHandle < ( ) > ,
25
+ impl fmt:: Debug for ProcMacroProcessSrv {
26
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
27
+ f. debug_struct ( "ProcMacroProcessSrv" ) . field ( "process" , & self . process ) . finish ( )
28
+ }
30
29
}
31
30
32
31
impl ProcMacroProcessSrv {
33
32
pub ( crate ) fn run (
34
33
process_path : PathBuf ,
35
34
args : impl IntoIterator < Item = impl AsRef < OsStr > > ,
36
- ) -> io:: Result < ( ProcMacroProcessThread , ProcMacroProcessSrv ) > {
37
- let process = Process :: run ( process_path, args) ?;
38
-
39
- let ( task_tx, task_rx) = bounded ( 0 ) ;
40
- let handle = jod_thread:: Builder :: new ( )
41
- . name ( "ProcMacroClient" . to_owned ( ) )
42
- . spawn ( move || {
43
- client_loop ( task_rx, process) ;
44
- } )
45
- . expect ( "failed to spawn thread" ) ;
46
-
47
- let task_tx = Arc :: new ( task_tx) ;
48
- let srv = ProcMacroProcessSrv { inner : Arc :: downgrade ( & task_tx) } ;
49
- let thread = ProcMacroProcessThread { handle, sender : task_tx } ;
50
-
51
- Ok ( ( thread, srv) )
35
+ ) -> io:: Result < ProcMacroProcessSrv > {
36
+ let mut process = Process :: run ( process_path, args) ?;
37
+ let ( stdin, stdout) = process. stdio ( ) . expect ( "couldn't access child stdio" ) ;
38
+
39
+ let srv = ProcMacroProcessSrv {
40
+ process : Mutex :: new ( process) ,
41
+ stdio : Mutex :: new ( ( stdin, stdout) ) ,
42
+ } ;
43
+
44
+ Ok ( srv)
52
45
}
53
46
54
47
pub ( crate ) fn find_proc_macros (
@@ -65,38 +58,15 @@ impl ProcMacroProcessSrv {
65
58
where
66
59
R : TryFrom < Response , Error = & ' static str > ,
67
60
{
68
- let ( result_tx, result_rx) = bounded ( 0 ) ;
69
- let sender = match self . inner . upgrade ( ) {
70
- None => return Err ( tt:: ExpansionError :: Unknown ( "proc macro process is closed" . into ( ) ) ) ,
71
- Some ( it) => it,
72
- } ;
73
- sender
74
- . send ( Task { req, result_tx } )
75
- . map_err ( |_| tt:: ExpansionError :: Unknown ( "proc macro server crashed" . into ( ) ) ) ?;
61
+ let mut guard = self . stdio . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
62
+ let stdio = & mut * guard;
63
+ let ( stdin, stdout) = ( & mut stdio. 0 , & mut stdio. 1 ) ;
76
64
77
- let res = result_rx
78
- . recv ( )
79
- . map_err ( |_| tt:: ExpansionError :: Unknown ( "proc macro server crashed" . into ( ) ) ) ?;
80
-
81
- match res {
82
- Some ( Response :: Error ( err) ) => Err ( tt:: ExpansionError :: ExpansionError ( err. message ) ) ,
83
- Some ( res) => Ok ( res. try_into ( ) . map_err ( |err| {
84
- tt:: ExpansionError :: Unknown ( format ! ( "Fail to get response, reason : {:#?} " , err) )
85
- } ) ?) ,
86
- None => Err ( tt:: ExpansionError :: Unknown ( "Empty result" . into ( ) ) ) ,
87
- }
88
- }
89
- }
90
-
91
- fn client_loop ( task_rx : Receiver < Task > , mut process : Process ) {
92
- let ( mut stdin, mut stdout) = process. stdio ( ) . expect ( "couldn't access child stdio" ) ;
93
-
94
- let mut buf = String :: new ( ) ;
95
-
96
- for Task { req, result_tx } in task_rx {
97
- match send_request ( & mut stdin, & mut stdout, req, & mut buf) {
98
- Ok ( res) => result_tx. send ( res) . unwrap ( ) ,
65
+ let mut buf = String :: new ( ) ;
66
+ let res = match send_request ( stdin, stdout, req, & mut buf) {
67
+ Ok ( res) => res,
99
68
Err ( err) => {
69
+ let mut process = self . process . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
100
70
log:: error!(
101
71
"proc macro server crashed, server process state: {:?}, server request error: {:?}" ,
102
72
process. child. try_wait( ) ,
@@ -106,19 +76,21 @@ fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
106
76
code : ErrorCode :: ServerErrorEnd ,
107
77
message : "proc macro server crashed" . into ( ) ,
108
78
} ) ;
109
- result_tx. send ( res. into ( ) ) . unwrap ( ) ;
110
- // Exit the thread.
111
- break ;
79
+ Some ( res)
112
80
}
81
+ } ;
82
+
83
+ match res {
84
+ Some ( Response :: Error ( err) ) => Err ( tt:: ExpansionError :: ExpansionError ( err. message ) ) ,
85
+ Some ( res) => Ok ( res. try_into ( ) . map_err ( |err| {
86
+ tt:: ExpansionError :: Unknown ( format ! ( "Fail to get response, reason : {:#?} " , err) )
87
+ } ) ?) ,
88
+ None => Err ( tt:: ExpansionError :: Unknown ( "Empty result" . into ( ) ) ) ,
113
89
}
114
90
}
115
91
}
116
92
117
- struct Task {
118
- req : Request ,
119
- result_tx : Sender < Option < Response > > ,
120
- }
121
-
93
+ #[ derive( Debug ) ]
122
94
struct Process {
123
95
child : JodChild ,
124
96
}
@@ -133,7 +105,7 @@ impl Process {
133
105
Ok ( Process { child } )
134
106
}
135
107
136
- fn stdio ( & mut self ) -> Option < ( impl Write , impl BufRead ) > {
108
+ fn stdio ( & mut self ) -> Option < ( ChildStdin , BufReader < ChildStdout > ) > {
137
109
let stdin = self . child . stdin . take ( ) ?;
138
110
let stdout = self . child . stdout . take ( ) ?;
139
111
let read = BufReader :: new ( stdout) ;
0 commit comments