aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock42
-rw-r--r--Cargo.toml1
-rw-r--r--src/main.rs52
3 files changed, 85 insertions, 10 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f9a0b2e..3a0e669 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5,6 +5,7 @@ dependencies = [
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -16,6 +17,16 @@ dependencies = [
]
[[package]]
+name = "bitflags"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "env_logger"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -57,6 +68,19 @@ dependencies = [
]
[[package]]
+name = "nix"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "regex"
version = "0.1.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -74,6 +98,19 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "rustc_version"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "thread-id"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -96,6 +133,11 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "void"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index e8cd7e6..be7fd7f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,6 +4,7 @@ version = "0.1.0"
authors = ["bnewbold <bnewbold@robocracy.org>"]
[dependencies]
+nix = "0.7"
log = "0.3"
env_logger = "0.3"
getopts = "^0.2"
diff --git a/src/main.rs b/src/main.rs
index d87f037..d4221dc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -19,28 +19,45 @@
extern crate getopts;
extern crate log;
extern crate env_logger;
+extern crate nix;
use std::env;
use std::u64;
use std::str::FromStr;
-use std::{time, thread};
use std::process::exit;
use std::process::Command;
+use std::process::Child;
+use std::net::SocketAddr;
+use std::net::TcpListener;
+use std::net::ToSocketAddrs;
use getopts::Options;
-fn run(prog: Vec<String>, number: u64) {
+use std::os::unix::io::IntoRawFd;
+fn run(binds: Vec<TcpListener>, mut prog: Command, number: u64) {
+ prog.env("EINHORN_FD_COUNT", binds.len().to_string());
+ // This iterator destroys the TcpListeners
+ for (i, b) in binds.into_iter().enumerate() {
+ let orig_fd = b.into_raw_fd();
+ // Duplicate, which also clears the CLOEXEC flag
+ //let fd = nix::fcntl::fcntl(nix::fcntl::FcntlArg::F_DUPFD(orig_fd)).unwrap();
+ let fd = nix::unistd::dup(orig_fd).unwrap();
+ println!("fd={} FD_CLOEXEC={}", fd, nix::fcntl::fcntl(fd, nix::fcntl::FcntlArg::F_GETFD).unwrap());
+ prog.env(format!("EINHORN_FD_{}", i), fd.to_string());
+ // NB: is fd getting destroyed here?
+ }
+
+ let mut children: Vec<Child> = vec![];
for _ in 0..number {
println!("Running!");
- Command::new(&prog[0])
- .args(&prog[1..])
- .spawn()
- .expect("command failed");
+ children.push(prog.spawn().expect("error spawning"));
}
- println!("Sleeping for 1sec");
- thread::sleep(time::Duration::from_secs(1));
+ println!("Waiting for all children to die");
+ for mut c in children {
+ c.wait().unwrap();
+ }
}
fn print_usage(opts: Options) {
@@ -54,6 +71,7 @@ fn main() {
let args: Vec<String> = env::args().collect();
let mut opts = Options::new();
+ opts.parsing_style(getopts::ParsingStyle::StopAtFirstFree);
opts.optflag("h", "help", "print this help menu");
opts.optflag("v", "verbose", "more debugging messages");
opts.optopt("n", "number", "how many program copies to spawn", "COUNT");
@@ -70,10 +88,16 @@ fn main() {
}
let number: u64 = match matches.opt_str("number") {
- Some(n) => u64::from_str(&n).unwrap(),
+ Some(n) => u64::from_str(&n).expect("number arg should be an integer"),
None => 1
};
+ let sock_addrs: Vec<SocketAddr> = matches.opt_strs("bind").iter().map(|b| {
+ //let sa: SocketAddr = b.to_socket_addrs().unwrap().next().unwrap();
+ //sa
+ b.to_socket_addrs().unwrap().next().unwrap()
+ }).collect();
+
let program_and_args = if !matches.free.is_empty() {
matches.free
} else {
@@ -88,5 +112,13 @@ fn main() {
}
builder.init().unwrap();
- run(program_and_args, number);
+ let binds: Vec<TcpListener> = sock_addrs.iter().map(|sa| {
+ TcpListener::bind(sa).unwrap()
+ }).collect();
+
+ let mut prog = Command::new(&program_and_args[0]);
+ prog.args(&program_and_args[1..]);
+
+ run(binds, prog, number);
+ exit(0);
}