aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorbnewbold <bnewbold@robocracy.org>2016-10-03 20:06:31 -0700
committerbnewbold <bnewbold@robocracy.org>2016-10-03 20:06:31 -0700
commit894772fd48cf0ede4a1ce4a90aa7694674806200 (patch)
tree3d9ee39276cd7ee8e25cf2a8d7f0fbc6595d8c9f /src
parent1febaf12b62603d0224468023d8a78169c2d2b0d (diff)
downloadeinhyrningsins-894772fd48cf0ede4a1ce4a90aa7694674806200.tar.gz
einhyrningsins-894772fd48cf0ede4a1ce4a90aa7694674806200.zip
basic file descriptor passing
Diffstat (limited to 'src')
-rw-r--r--src/main.rs52
1 files changed, 42 insertions, 10 deletions
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);
}