Change:
I'm on OSX 10.8.4, x8664, latest Rust on master. And to head off any concerns about my file handle limits: I ran into this when stress-testing my web sockets library. After just a couple hundred connections, some connections were being refused at random. The only thing I could see was some output with saying . I've come up with a smaller test case that brings this out with some spectacular errors: Fails less often with 100-200 connections. The errors are different every time I run this with . Here's the end of one run: Another: Another: And lastly:
cc
Oh dear that's bad, thanks for the small issue! I will definitely investigate.
What is the result of though? Just calling is only the maximum file size (unless OSX is different).
you're right! So I set it to a higher value and things seem fine now. Sorry about that. Though, It's still a surprising way for the runtime to fail, and clearly something is still wrong there.
Despite OSX having small file descriptor limits, this is a serious bug that I'd like to address with the runtime. Something funny is going on.
With applied, I am unable to reproduce this on OSX. I am not convinced that it fixes anything, but I'm no longer seeing any scary assertions.
I take that back, I was using , not (silly me)
I attempted to debug this issue on linux, and I quickly ran into two problems. The first is an assertion fixed by , and the other is filed as Sadly none of this seems related to the assertions on OSX, so I'll continue to investigate there. If only OSX still had valgrind...

Discussion:
// option. This file may not be copied, modified, or distributed // except according to those terms. <del> use std::libc; </del> use std::io::IoError; <ins> use std::libc; use std::ptr; </ins> use std::rt::rtio::RtioTTY; use homing::{HomingIO, HomeHandle};

// If this file descriptor is indeed guessed to be a tty, then go ahead // with attempting to open it as a tty. let handle = UvHandle::alloc(None::<TtyWatcher>, uvll::UV_TTY); <ins> let mut watcher = TtyWatcher { tty: handle, stream: StreamWatcher::new(handle), home: io.make_handle(), fd: fd, }; </ins> match unsafe { uvll::uv_tty_init(io.uv_loop(), handle, fd as libc::c_int, readable as libc::c_int) } { <del> 0 => { Ok(TtyWatcher { tty: handle, stream: StreamWatcher::new(handle), home: io.make_handle(), fd: fd, }) } </del> <ins> 0 => Ok(watcher), </ins> n => { <del> unsafe { uvll::free_handle(handle) } </del> <ins> // On windows, libuv returns errors before initializing the // handle, so our only cleanup is to free the handle itself if cfg!(windows) { unsafe { uvll::free_handle(handle); } watcher.tty = ptr::null(); } </ins> Err(UvError(n)) } }

impl Drop for TtyWatcher { fn drop(&mut self) { <del> let _m = self.fire_homing_missile(); self.close_async_(); </del> <ins> if !self.tty.is_null() { let _m = self.fire_homing_missile(); self.close_async_(); } </ins> } }

<ins> // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // ignore-linux see joyent/libuv#1189 // ignore-fast // ignore-android needs extra network permissions // exec-env:RUST_LOG=debug use std::libc; use std::io::net::ip::{Ipv4Addr, SocketAddr}; use std::io::net::tcp::{TcpListener, TcpStream}; use std::io::{Acceptor, Listener}; fn main() { // This test has a chance to time out, try to not let it time out spawn(proc() { use std::io::timer; timer::sleep(30 * 1000); println!("timed out!"); unsafe { libc::exit(1) } }); let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 0 }; let (p, c) = Chan::new(); spawn(proc() { let mut listener = TcpListener::bind(addr).unwrap(); c.send(listener.socket_name().unwrap()); let mut acceptor = listener.listen(); loop { let mut stream = match acceptor.accept() { Ok(stream) => stream, Err(error) => { debug!("accept failed: {:?}", error); continue; } }; stream.read_byte(); stream.write([2]); } }); let addr = p.recv(); let (p, c) = Chan::new(); for _ in range(0, 1000) { let c = c.clone(); spawn(proc() { match TcpStream::connect(addr) { Ok(stream) => { let mut stream = stream; stream.write([1]); let mut buf = [0]; stream.read(buf); }, Err(e) => debug!("{:?}", e) } c.send(()); }); } // Wait for all clients to exit, but don't wait for the server to exit. The // server just runs infinitely. drop(c); for _ in range(0, 1000) { p.recv(); } unsafe { libc::exit(0) } } </ins>