1
- use std:: cell:: RefCell ;
2
1
use std:: ffi:: OsString ;
3
2
use std:: fs:: File ;
4
3
use std:: io:: ErrorKind ;
4
+ use std:: sync:: { RwLock , RwLockReadGuard , RwLockWriteGuard } ;
5
5
use std:: time:: Duration ;
6
6
7
7
use crate :: function:: OptionalArg ;
8
8
use crate :: obj:: objbytes:: PyBytesRef ;
9
9
use crate :: obj:: objlist:: PyListRef ;
10
10
use crate :: obj:: objstr:: { self , PyStringRef } ;
11
11
use crate :: obj:: objtype:: PyClassRef ;
12
- use crate :: pyobject:: { Either , IntoPyObject , PyObjectRef , PyRef , PyResult , PyValue } ;
12
+ use crate :: pyobject:: { Either , IntoPyObject , PyObjectRef , PyRef , PyResult , PyValue , ThreadSafe } ;
13
13
use crate :: stdlib:: io:: io_open;
14
14
use crate :: stdlib:: os:: { convert_io_error, raw_file_number, rust_file} ;
15
15
use crate :: vm:: VirtualMachine ;
16
16
17
17
#[ derive( Debug ) ]
18
18
struct Popen {
19
- process : RefCell < subprocess:: Popen > ,
19
+ process : RwLock < subprocess:: Popen > ,
20
20
args : PyObjectRef ,
21
21
}
22
22
23
+ impl ThreadSafe for Popen { }
24
+
23
25
impl PyValue for Popen {
24
26
fn class ( vm : & VirtualMachine ) -> PyClassRef {
25
27
vm. class ( "_subprocess" , "Popen" )
@@ -103,6 +105,14 @@ fn convert_to_file_io(file: &Option<File>, mode: &str, vm: &VirtualMachine) -> P
103
105
}
104
106
105
107
impl PopenRef {
108
+ fn borrow_process ( & self ) -> RwLockReadGuard < ' _ , subprocess:: Popen > {
109
+ self . process . read ( ) . unwrap ( )
110
+ }
111
+
112
+ fn borrow_process_mut ( & self ) -> RwLockWriteGuard < ' _ , subprocess:: Popen > {
113
+ self . process . write ( ) . unwrap ( )
114
+ }
115
+
106
116
fn new ( cls : PyClassRef , args : PopenArgs , vm : & VirtualMachine ) -> PyResult < PopenRef > {
107
117
let stdin = convert_redirection ( args. stdin , vm) ?;
108
118
let stdout = convert_redirection ( args. stdout , vm) ?;
@@ -130,27 +140,26 @@ impl PopenRef {
130
140
. map_err ( |s| vm. new_os_error ( format ! ( "Could not start program: {}" , s) ) ) ?;
131
141
132
142
Popen {
133
- process : RefCell :: new ( process) ,
143
+ process : RwLock :: new ( process) ,
134
144
args : args. args . into_object ( ) ,
135
145
}
136
146
. into_ref_with_type ( vm, cls)
137
147
}
138
148
139
149
fn poll ( self ) -> Option < subprocess:: ExitStatus > {
140
- self . process . borrow_mut ( ) . poll ( )
150
+ self . borrow_process_mut ( ) . poll ( )
141
151
}
142
152
143
153
fn return_code ( self ) -> Option < subprocess:: ExitStatus > {
144
- self . process . borrow ( ) . exit_status ( )
154
+ self . borrow_process ( ) . exit_status ( )
145
155
}
146
156
147
157
fn wait ( self , args : PopenWaitArgs , vm : & VirtualMachine ) -> PyResult < i64 > {
148
158
let timeout = match args. timeout {
149
159
Some ( timeout) => self
150
- . process
151
- . borrow_mut ( )
160
+ . borrow_process_mut ( )
152
161
. wait_timeout ( Duration :: new ( timeout, 0 ) ) ,
153
- None => self . process . borrow_mut ( ) . wait ( ) . map ( Some ) ,
162
+ None => self . borrow_process_mut ( ) . wait ( ) . map ( Some ) ,
154
163
}
155
164
. map_err ( |s| vm. new_os_error ( format ! ( "Could not start program: {}" , s) ) ) ?;
156
165
if let Some ( exit) = timeout {
@@ -167,27 +176,25 @@ impl PopenRef {
167
176
}
168
177
169
178
fn stdin ( self , vm : & VirtualMachine ) -> PyResult {
170
- convert_to_file_io ( & self . process . borrow ( ) . stdin , "wb" , vm)
179
+ convert_to_file_io ( & self . borrow_process ( ) . stdin , "wb" , vm)
171
180
}
172
181
173
182
fn stdout ( self , vm : & VirtualMachine ) -> PyResult {
174
- convert_to_file_io ( & self . process . borrow ( ) . stdout , "rb" , vm)
183
+ convert_to_file_io ( & self . borrow_process ( ) . stdout , "rb" , vm)
175
184
}
176
185
177
186
fn stderr ( self , vm : & VirtualMachine ) -> PyResult {
178
- convert_to_file_io ( & self . process . borrow ( ) . stderr , "rb" , vm)
187
+ convert_to_file_io ( & self . borrow_process ( ) . stderr , "rb" , vm)
179
188
}
180
189
181
190
fn terminate ( self , vm : & VirtualMachine ) -> PyResult < ( ) > {
182
- self . process
183
- . borrow_mut ( )
191
+ self . borrow_process_mut ( )
184
192
. terminate ( )
185
193
. map_err ( |err| convert_io_error ( vm, err) )
186
194
}
187
195
188
196
fn kill ( self , vm : & VirtualMachine ) -> PyResult < ( ) > {
189
- self . process
190
- . borrow_mut ( )
197
+ self . borrow_process_mut ( )
191
198
. kill ( )
192
199
. map_err ( |err| convert_io_error ( vm, err) )
193
200
}
@@ -202,7 +209,7 @@ impl PopenRef {
202
209
OptionalArg :: Present ( ref bytes) => Some ( bytes. get_value ( ) . to_vec ( ) ) ,
203
210
OptionalArg :: Missing => None ,
204
211
} ;
205
- let mut communicator = self . process . borrow_mut ( ) . communicate_start ( bytes) ;
212
+ let mut communicator = self . borrow_process_mut ( ) . communicate_start ( bytes) ;
206
213
if let OptionalArg :: Present ( timeout) = args. timeout {
207
214
communicator = communicator. limit_time ( Duration :: new ( timeout, 0 ) ) ;
208
215
}
@@ -217,7 +224,7 @@ impl PopenRef {
217
224
}
218
225
219
226
fn pid ( self ) -> Option < u32 > {
220
- self . process . borrow ( ) . pid ( )
227
+ self . borrow_process ( ) . pid ( )
221
228
}
222
229
223
230
fn enter ( self ) -> Self {
@@ -230,7 +237,7 @@ impl PopenRef {
230
237
_exception_value : PyObjectRef ,
231
238
_traceback : PyObjectRef ,
232
239
) {
233
- let mut process = self . process . borrow_mut ( ) ;
240
+ let mut process = self . borrow_process_mut ( ) ;
234
241
process. stdout . take ( ) ;
235
242
process. stdin . take ( ) ;
236
243
process. stderr . take ( ) ;
0 commit comments