summaryrefslogtreecommitdiff
path: root/src/resources.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/resources.rs')
-rw-r--r--src/resources.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/resources.rs b/src/resources.rs
index 90b7ce772..36e0d9486 100644
--- a/src/resources.rs
+++ b/src/resources.rs
@@ -20,12 +20,14 @@ use tokio_write;
use futures;
use futures::future::{Either, FutureResult};
+use futures::Future;
use futures::Poll;
use hyper;
use std;
use std::collections::HashMap;
use std::io::{Error, Read, Write};
use std::net::{Shutdown, SocketAddr};
+use std::process::ExitStatus;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::sync::Mutex;
@@ -33,6 +35,7 @@ use tokio;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::net::TcpStream;
use tokio_io;
+use tokio_process;
pub type ResourceId = u32; // Sometimes referred to RID.
@@ -63,6 +66,10 @@ enum Repr {
TcpStream(tokio::net::TcpStream),
HttpBody(HttpBody),
Repl(Repl),
+ Child(tokio_process::Child),
+ ChildStdin(tokio_process::ChildStdin),
+ ChildStdout(tokio_process::ChildStdout),
+ ChildStderr(tokio_process::ChildStderr),
}
pub fn table_entries() -> Vec<(u32, String)> {
@@ -94,6 +101,10 @@ fn inspect_repr(repr: &Repr) -> String {
Repr::TcpStream(_) => "tcpStream",
Repr::HttpBody(_) => "httpBody",
Repr::Repl(_) => "repl",
+ Repr::Child(_) => "child",
+ Repr::ChildStdin(_) => "childStdin",
+ Repr::ChildStdout(_) => "childStdout",
+ Repr::ChildStderr(_) => "childStderr",
};
String::from(h_repr)
@@ -160,6 +171,8 @@ impl AsyncRead for Resource {
Repr::Stdin(ref mut f) => f.poll_read(buf),
Repr::TcpStream(ref mut f) => f.poll_read(buf),
Repr::HttpBody(ref mut f) => f.poll_read(buf),
+ Repr::ChildStdout(ref mut f) => f.poll_read(buf),
+ Repr::ChildStderr(ref mut f) => f.poll_read(buf),
_ => panic!("Cannot read"),
},
}
@@ -187,6 +200,7 @@ impl AsyncWrite for Resource {
Repr::Stdout(ref mut f) => f.poll_write(buf),
Repr::Stderr(ref mut f) => f.poll_write(buf),
Repr::TcpStream(ref mut f) => f.poll_write(buf),
+ Repr::ChildStdin(ref mut f) => f.poll_write(buf),
_ => panic!("Cannot write"),
},
}
@@ -244,6 +258,80 @@ pub fn add_repl(repl: Repl) -> Resource {
Resource { rid }
}
+pub struct ChildResources {
+ pub child_rid: ResourceId,
+ pub stdin_rid: Option<ResourceId>,
+ pub stdout_rid: Option<ResourceId>,
+ pub stderr_rid: Option<ResourceId>,
+}
+
+pub fn add_child(mut c: tokio_process::Child) -> ChildResources {
+ let child_rid = new_rid();
+ let mut tg = RESOURCE_TABLE.lock().unwrap();
+
+ let mut resources = ChildResources {
+ child_rid,
+ stdin_rid: None,
+ stdout_rid: None,
+ stderr_rid: None,
+ };
+
+ if c.stdin().is_some() {
+ let stdin = c.stdin().take().unwrap();
+ let rid = new_rid();
+ let r = tg.insert(rid, Repr::ChildStdin(stdin));
+ assert!(r.is_none());
+ resources.stdin_rid = Some(rid);
+ }
+ if c.stdout().is_some() {
+ let stdout = c.stdout().take().unwrap();
+ let rid = new_rid();
+ let r = tg.insert(rid, Repr::ChildStdout(stdout));
+ assert!(r.is_none());
+ resources.stdout_rid = Some(rid);
+ }
+ if c.stderr().is_some() {
+ let stderr = c.stderr().take().unwrap();
+ let rid = new_rid();
+ let r = tg.insert(rid, Repr::ChildStderr(stderr));
+ assert!(r.is_none());
+ resources.stderr_rid = Some(rid);
+ }
+
+ let r = tg.insert(child_rid, Repr::Child(c));
+ assert!(r.is_none());
+
+ return resources;
+}
+
+pub struct ChildStatus {
+ rid: ResourceId,
+}
+
+// Invert the dumbness that tokio_process causes by making Child itself a future.
+impl Future for ChildStatus {
+ type Item = ExitStatus;
+ type Error = DenoError;
+
+ fn poll(&mut self) -> Poll<ExitStatus, DenoError> {
+ let mut table = RESOURCE_TABLE.lock().unwrap();
+ let maybe_repr = table.get_mut(&self.rid);
+ match maybe_repr {
+ Some(Repr::Child(ref mut child)) => child.poll().map_err(DenoError::from),
+ _ => Err(bad_resource()),
+ }
+ }
+}
+
+pub fn child_status(rid: ResourceId) -> DenoResult<ChildStatus> {
+ let mut table = RESOURCE_TABLE.lock().unwrap();
+ let maybe_repr = table.get_mut(&rid);
+ match maybe_repr {
+ Some(Repr::Child(ref mut _child)) => Ok(ChildStatus { rid }),
+ _ => Err(bad_resource()),
+ }
+}
+
pub fn readline(rid: ResourceId, prompt: &str) -> DenoResult<String> {
let mut table = RESOURCE_TABLE.lock().unwrap();
let maybe_repr = table.get_mut(&rid);