| //@ run-pass |
| //@ ignore-android needs extra network permissions |
| //@ needs-threads |
| //@ ignore-netbsd system ulimit (Too many open files) |
| //@ ignore-openbsd system ulimit (Too many open files) |
| |
| use std::io::prelude::*; |
| use std::net::{TcpListener, TcpStream}; |
| use std::process; |
| use std::sync::mpsc::channel; |
| use std::thread::{self, Builder}; |
| use std::time::Duration; |
| |
| const TARGET_CNT: usize = 200; |
| |
| fn main() { |
| // This test has a chance to time out, try to not let it time out |
| thread::spawn(move || -> () { |
| thread::sleep(Duration::from_secs(30)); |
| process::exit(1); |
| }); |
| |
| let listener = TcpListener::bind("127.0.0.1:0").unwrap(); |
| let addr = listener.local_addr().unwrap(); |
| thread::spawn(move || -> () { |
| loop { |
| let mut stream = match listener.accept() { |
| Ok(stream) => stream.0, |
| Err(_) => continue, |
| }; |
| let _ = stream.read(&mut [0]); |
| let _ = stream.write(&[2]); |
| } |
| }); |
| |
| let (tx, rx) = channel(); |
| |
| let mut spawned_cnt = 0; |
| for _ in 0..TARGET_CNT { |
| let tx = tx.clone(); |
| let res = Builder::new().stack_size(64 * 1024).spawn(move || { |
| match TcpStream::connect(addr) { |
| Ok(mut stream) => { |
| let _ = stream.write(&[1]); |
| let _ = stream.read(&mut [0]); |
| } |
| Err(..) => {} |
| } |
| tx.send(()).unwrap(); |
| }); |
| if let Ok(_) = res { |
| spawned_cnt += 1; |
| }; |
| } |
| |
| // Wait for all clients to exit, but don't wait for the server to exit. The |
| // server just runs infinitely. |
| drop(tx); |
| for _ in 0..spawned_cnt { |
| rx.recv().unwrap(); |
| } |
| assert_eq!(spawned_cnt, TARGET_CNT); |
| process::exit(0); |
| } |