Skip to content

Commit 9c12b95

Browse files
committed
Support timeout in Popen.communicate
1 parent 7cdaba7 commit 9c12b95

File tree

4 files changed

+21
-9
lines changed

4 files changed

+21
-9
lines changed

Cargo.lock

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/snippets/stdlib_subprocess.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,7 @@
5151
p = subprocess.Popen(["echo", "test"], stdout=subprocess.PIPE)
5252
(stdout, stderr) = p.communicate()
5353
assert stdout.strip() == b"test"
54+
55+
p = subprocess.Popen(["sleep", "5"], stdout=subprocess.PIPE)
56+
with assert_raises(subprocess.TimeoutExpired):
57+
p.communicate(timeout=1)

vm/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ adler32 = "1.0.3"
8585
flate2 = { version = "1.0", features = ["zlib"], default-features = false }
8686
libz-sys = "1.0.25"
8787
gethostname = "0.2.0"
88-
subprocess = "0.1.18"
88+
subprocess = "0.2.2"
8989
num_cpus = "1"
9090
socket2 = { version = "0.3", features = ["unix"] }
9191

vm/src/stdlib/subprocess.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::cell::RefCell;
22
use std::ffi::OsString;
33
use std::fs::File;
4+
use std::io::ErrorKind;
45
use std::time::Duration;
56

67
use subprocess;
@@ -191,13 +192,21 @@ impl PopenRef {
191192
vm: &VirtualMachine,
192193
) -> PyResult<(Option<Vec<u8>>, Option<Vec<u8>>)> {
193194
let bytes = match args.input {
194-
OptionalArg::Present(ref bytes) => Some(bytes.get_value()),
195+
OptionalArg::Present(ref bytes) => Some(bytes.get_value().to_vec()),
195196
OptionalArg::Missing => None,
196197
};
197-
self.process
198-
.borrow_mut()
199-
.communicate_bytes(bytes)
200-
.map_err(|err| convert_io_error(vm, err))
198+
let mut communicator = self.process.borrow_mut().communicate_start(bytes);
199+
if let OptionalArg::Present(timeout) = args.timeout {
200+
communicator = communicator.limit_time(Duration::new(timeout, 0));
201+
}
202+
communicator.read().map_err(|err| {
203+
if err.error.kind() == ErrorKind::TimedOut {
204+
let timeout_expired = vm.try_class("_subprocess", "TimeoutExpired").unwrap();
205+
vm.new_exception_msg(timeout_expired, "Timeout".to_string())
206+
} else {
207+
convert_io_error(vm, err.error)
208+
}
209+
})
201210
}
202211

203212
fn pid(self, _vm: &VirtualMachine) -> Option<u32> {

0 commit comments

Comments
 (0)