about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-12-19 11:29:39 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-12-30 14:33:59 -0800
commit9e224c2bf18ebf8f871efb2e1aba43ed7970ebb7 (patch)
treeda18d5791e6841a1aa6a9469baca155d4ca9828d /src/libstd/sys
parentd2368c3c11ddab9d812c4ddec2e44579326ad347 (diff)
downloadrust-9e224c2bf18ebf8f871efb2e1aba43ed7970ebb7.tar.gz
rust-9e224c2bf18ebf8f871efb2e1aba43ed7970ebb7.zip
std: Re-enable at_exit()
The new semantics of this function are that the callbacks are run when the *main
thread* exits, not when all threads have exited. This implies that other threads
may still be running when the `at_exit` callbacks are invoked and users need to
be prepared for this situation.

Users in the standard library have been audited in accordance to these new rules
as well.

Closes #20012
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/common/helper_thread.rs31
-rw-r--r--src/libstd/sys/common/mod.rs2
-rw-r--r--src/libstd/sys/common/mutex.rs1
-rw-r--r--src/libstd/sys/common/net.rs6
-rw-r--r--src/libstd/sys/common/rwlock.rs1
-rw-r--r--src/libstd/sys/common/stack.rs31
-rw-r--r--src/libstd/sys/common/thread_info.rs10
-rw-r--r--src/libstd/sys/common/thread_local.rs5
-rw-r--r--src/libstd/sys/unix/backtrace.rs12
-rw-r--r--src/libstd/sys/unix/mod.rs16
-rw-r--r--src/libstd/sys/unix/mutex.rs2
-rw-r--r--src/libstd/sys/unix/os.rs9
-rw-r--r--src/libstd/sys/unix/pipe.rs2
-rw-r--r--src/libstd/sys/unix/process.rs15
-rw-r--r--src/libstd/sys/unix/rwlock.rs1
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs1
-rw-r--r--src/libstd/sys/unix/tcp.rs4
-rw-r--r--src/libstd/sys/unix/timer.rs11
-rw-r--r--src/libstd/sys/unix/tty.rs1
-rw-r--r--src/libstd/sys/windows/backtrace.rs31
-rw-r--r--src/libstd/sys/windows/c.rs1
-rw-r--r--src/libstd/sys/windows/fs.rs12
-rw-r--r--src/libstd/sys/windows/mod.rs24
-rw-r--r--src/libstd/sys/windows/os.rs4
-rw-r--r--src/libstd/sys/windows/pipe.rs8
-rw-r--r--src/libstd/sys/windows/process.rs15
-rw-r--r--src/libstd/sys/windows/stack_overflow.rs10
-rw-r--r--src/libstd/sys/windows/tcp.rs9
-rw-r--r--src/libstd/sys/windows/thread.rs2
-rw-r--r--src/libstd/sys/windows/thread_local.rs11
-rw-r--r--src/libstd/sys/windows/timer.rs7
-rw-r--r--src/libstd/sys/windows/tty.rs8
32 files changed, 119 insertions, 184 deletions
diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs
index 9ef1c33312f..7093c417b11 100644
--- a/src/libstd/sys/common/helper_thread.rs
+++ b/src/libstd/sys/common/helper_thread.rs
@@ -20,6 +20,8 @@
 //! can be created in the future and there must be no active timers at that
 //! time.
 
+#![macro_escape]
+
 use prelude::*;
 
 use cell::UnsafeCell;
@@ -68,6 +70,17 @@ struct RaceBox(helper_signal::signal);
 unsafe impl Send for RaceBox {}
 unsafe impl Sync for RaceBox {}
 
+macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
+    static $name: Helper<$m> = Helper {
+        lock: ::sync::MUTEX_INIT,
+        cond: ::sync::CONDVAR_INIT,
+        chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
+        signal: ::cell::UnsafeCell { value: 0 },
+        initialized: ::cell::UnsafeCell { value: false },
+        shutdown: ::cell::UnsafeCell { value: false },
+    };
+) }
+
 impl<M: Send> Helper<M> {
     /// Lazily boots a helper thread, becoming a no-op if the helper has already
     /// been spawned.
@@ -84,7 +97,7 @@ impl<M: Send> Helper<M> {
     {
         unsafe {
             let _guard = self.lock.lock().unwrap();
-            if !*self.initialized.get() {
+            if *self.chan.get() as uint == 0 {
                 let (tx, rx) = channel();
                 *self.chan.get() = mem::transmute(box tx);
                 let (receive, send) = helper_signal::new();
@@ -93,15 +106,17 @@ impl<M: Send> Helper<M> {
                 let receive = RaceBox(receive);
 
                 let t = f();
-                Thread::spawn(move |:| {
+                Thread::spawn(move || {
                     helper(receive.0, rx, t);
                     let _g = self.lock.lock().unwrap();
                     *self.shutdown.get() = true;
                     self.cond.notify_one()
                 }).detach();
 
-                rt::at_exit(move|:| { self.shutdown() });
+                rt::at_exit(move || { self.shutdown() });
                 *self.initialized.get() = true;
+            } else if *self.chan.get() as uint == 1 {
+                panic!("cannot continue usage after shutdown");
             }
         }
     }
@@ -116,7 +131,9 @@ impl<M: Send> Helper<M> {
             // Must send and *then* signal to ensure that the child receives the
             // message. Otherwise it could wake up and go to sleep before we
             // send the message.
-            assert!(!self.chan.get().is_null());
+            assert!(*self.chan.get() as uint != 0);
+            assert!(*self.chan.get() as uint != 1,
+                    "cannot continue usage after shutdown");
             (**self.chan.get()).send(msg);
             helper_signal::signal(*self.signal.get() as helper_signal::signal);
         }
@@ -129,9 +146,13 @@ impl<M: Send> Helper<M> {
             // returns.
             let mut guard = self.lock.lock().unwrap();
 
+            let ptr = *self.chan.get();
+            if ptr as uint == 1 {
+                panic!("cannot continue usage after shutdown");
+            }
             // Close the channel by destroying it
             let chan: Box<Sender<M>> = mem::transmute(*self.chan.get());
-            *self.chan.get() = 0 as *mut Sender<M>;
+            *self.chan.get() = 1 as *mut Sender<M>;
             drop(chan);
             helper_signal::signal(*self.signal.get() as helper_signal::signal);
 
diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs
index dc0ad08cdbe..6b2b325e638 100644
--- a/src/libstd/sys/common/mod.rs
+++ b/src/libstd/sys/common/mod.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![allow(missing_docs)]
-#![allow(dead_code)]
+#![macro_escape]
 
 use io::{mod, IoError, IoResult};
 use prelude::*;
diff --git a/src/libstd/sys/common/mutex.rs b/src/libstd/sys/common/mutex.rs
index 567c26956ef..322d2f202f7 100644
--- a/src/libstd/sys/common/mutex.rs
+++ b/src/libstd/sys/common/mutex.rs
@@ -29,6 +29,7 @@ impl Mutex {
     /// Behavior is undefined if the mutex is moved after the first method is
     /// called on the mutex.
     #[inline]
+    #[allow(dead_code)] // sys is not exported yet
     pub unsafe fn new() -> Mutex { Mutex(imp::Mutex::new()) }
 
     /// Lock the mutex blocking the current thread until it is available.
diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs
index 7a09137a225..24d22eb58c5 100644
--- a/src/libstd/sys/common/net.rs
+++ b/src/libstd/sys/common/net.rs
@@ -22,7 +22,9 @@ use io::{IoResult, IoError};
 use sys::{mod, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
           wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
           decode_error_detailed};
-use sync::{Mutex, MutexGuard};
+use sync::Mutex;
+#[cfg(not(target_os = "linux"))]
+use sync::MutexGuard;
 use sys_common::{mod, keep_going, short_write, timeout};
 use prelude::*;
 use cmp;
@@ -573,11 +575,13 @@ impl Drop for Inner {
     fn drop(&mut self) { unsafe { close_sock(self.fd); } }
 }
 
+#[cfg(not(target_os = "linux"))]
 pub struct Guard<'a> {
     pub fd: sock_t,
     pub guard: MutexGuard<'a, ()>,
 }
 
+#[cfg(not(target_os = "linux"))]
 #[unsafe_destructor]
 impl<'a> Drop for Guard<'a> {
     fn drop(&mut self) {
diff --git a/src/libstd/sys/common/rwlock.rs b/src/libstd/sys/common/rwlock.rs
index df016b9e293..b7c4cfcd0f5 100644
--- a/src/libstd/sys/common/rwlock.rs
+++ b/src/libstd/sys/common/rwlock.rs
@@ -26,6 +26,7 @@ impl RWLock {
     /// Usage of an RWLock is undefined if it is moved after its first use (any
     /// function calls below).
     #[inline]
+    #[allow(dead_code)] // sys is not exported yet
     pub unsafe fn new() -> RWLock { RWLock(imp::RWLock::new()) }
 
     /// Acquire shared access to the underlying lock, blocking the current
diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs
index 2a88e20c8fa..1966a9544e1 100644
--- a/src/libstd/sys/common/stack.rs
+++ b/src/libstd/sys/common/stack.rs
@@ -121,37 +121,6 @@ pub unsafe fn record_os_managed_stack_bounds(stack_lo: uint, _stack_hi: uint) {
     record_sp_limit(stack_lo + RED_ZONE);
 }
 
-#[inline(always)]
-pub unsafe fn record_rust_managed_stack_bounds(stack_lo: uint, stack_hi: uint) {
-    // When the old runtime had segmented stacks, it used a calculation that was
-    // "limit + RED_ZONE + FUDGE". The red zone was for things like dynamic
-    // symbol resolution, llvm function calls, etc. In theory this red zone
-    // value is 0, but it matters far less when we have gigantic stacks because
-    // we don't need to be so exact about our stack budget. The "fudge factor"
-    // was because LLVM doesn't emit a stack check for functions < 256 bytes in
-    // size. Again though, we have giant stacks, so we round all these
-    // calculations up to the nice round number of 20k.
-    record_sp_limit(stack_lo + RED_ZONE);
-
-    return target_record_stack_bounds(stack_lo, stack_hi);
-
-    #[cfg(not(windows))] #[inline(always)]
-    unsafe fn target_record_stack_bounds(_stack_lo: uint, _stack_hi: uint) {}
-
-    #[cfg(all(windows, target_arch = "x86"))] #[inline(always)]
-    unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
-        // stack range is at TIB: %fs:0x04 (top) and %fs:0x08 (bottom)
-        asm!("mov $0, %fs:0x04" :: "r"(stack_hi) :: "volatile");
-        asm!("mov $0, %fs:0x08" :: "r"(stack_lo) :: "volatile");
-    }
-    #[cfg(all(windows, target_arch = "x86_64"))] #[inline(always)]
-    unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
-        // stack range is at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
-        asm!("mov $0, %gs:0x08" :: "r"(stack_hi) :: "volatile");
-        asm!("mov $0, %gs:0x10" :: "r"(stack_lo) :: "volatile");
-    }
-}
-
 /// Records the current limit of the stack as specified by `end`.
 ///
 /// This is stored in an OS-dependent location, likely inside of the thread
diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs
index dc21feb17a8..f32c1ea3658 100644
--- a/src/libstd/sys/common/thread_info.rs
+++ b/src/libstd/sys/common/thread_info.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(dead_code)] // stack_guard isn't used right now on all platforms
+
 use core::prelude::*;
 
 use thread::Thread;
@@ -15,10 +17,6 @@ use cell::RefCell;
 use string::String;
 
 struct ThreadInfo {
-    // This field holds the known bounds of the stack in (lo, hi)
-    // form. Not all threads necessarily know their precise bounds,
-    // hence this is optional.
-    stack_bounds: (uint, uint),
     stack_guard: uint,
     thread: Thread,
 }
@@ -35,7 +33,6 @@ impl ThreadInfo {
         THREAD_INFO.with(|c| {
             if c.borrow().is_none() {
                 *c.borrow_mut() = Some(ThreadInfo {
-                    stack_bounds: (0, 0),
                     stack_guard: 0,
                     thread: NewThread::new(None),
                 })
@@ -53,10 +50,9 @@ pub fn stack_guard() -> uint {
     ThreadInfo::with(|info| info.stack_guard)
 }
 
-pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) {
+pub fn set(stack_guard: uint, thread: Thread) {
     THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
     THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
-        stack_bounds: stack_bounds,
         stack_guard: stack_guard,
         thread: thread,
     }));
diff --git a/src/libstd/sys/common/thread_local.rs b/src/libstd/sys/common/thread_local.rs
index fe7a7d8d037..cc69fbceacb 100644
--- a/src/libstd/sys/common/thread_local.rs
+++ b/src/libstd/sys/common/thread_local.rs
@@ -55,11 +55,11 @@
 //! ```
 
 #![allow(non_camel_case_types)]
+#![allow(dead_code)] // sys isn't exported yet
 
 use prelude::*;
 
 use sync::atomic::{mod, AtomicUint};
-use sync::{Mutex, Once, ONCE_INIT};
 
 use sys::thread_local as imp;
 
@@ -140,9 +140,6 @@ pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
     key: atomic::INIT_ATOMIC_UINT,
 };
 
-static INIT_KEYS: Once = ONCE_INIT;
-static mut KEYS: *mut Mutex<Vec<imp::Key>> = 0 as *mut _;
-
 impl StaticKey {
     /// Gets the value associated with this TLS key
     ///
diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs
index ddae9a132c3..0ec34fb1318 100644
--- a/src/libstd/sys/unix/backtrace.rs
+++ b/src/libstd/sys/unix/backtrace.rs
@@ -83,12 +83,12 @@
 /// to symbols. This is a bit of a hokey implementation as-is, but it works for
 /// all unix platforms we support right now, so it at least gets the job done.
 
+use prelude::*;
+
 use c_str::CString;
-use io::{IoResult, Writer};
+use io::IoResult;
 use libc;
 use mem;
-use option::Option::{mod, Some, None};
-use result::Result::{Ok, Err};
 use sync::{StaticMutex, MUTEX_INIT};
 
 use sys_common::backtrace::*;
@@ -151,7 +151,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> {
     // I/O done here is blocking I/O, not green I/O, so we don't have to
     // worry about this being a native vs green mutex.
     static LOCK: StaticMutex = MUTEX_INIT;
-    let _g = unsafe { LOCK.lock() };
+    let _g = LOCK.lock();
 
     try!(writeln!(w, "stack backtrace:"));
 
@@ -241,12 +241,8 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
 
 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
 fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
-    use iter::{Iterator, IteratorExt};
     use os;
-    use path::GenericPath;
-    use ptr::PtrExt;
     use ptr;
-    use slice::SliceExt;
 
     ////////////////////////////////////////////////////////////////////////
     // libbacktrace.h API
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 4b7ac8ff4d3..27fa7498673 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -10,30 +10,14 @@
 
 #![allow(missing_docs)]
 #![allow(non_camel_case_types)]
-#![allow(unused_imports)]
-#![allow(dead_code)]
-#![allow(unused_unsafe)]
-#![allow(unused_mut)]
 
 extern crate libc;
 
-use num;
 use num::{Int, SignedInt};
 use prelude::*;
 use io::{mod, IoResult, IoError};
 use sys_common::mkerr_libc;
 
-macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
-    static $name: Helper<$m> = Helper {
-        lock: ::sync::MUTEX_INIT,
-        cond: ::sync::CONDVAR_INIT,
-        chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
-        signal: ::cell::UnsafeCell { value: 0 },
-        initialized: ::cell::UnsafeCell { value: false },
-        shutdown: ::cell::UnsafeCell { value: false },
-    };
-) }
-
 pub mod backtrace;
 pub mod c;
 pub mod ext;
diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs
index 81f8659d6ae..c9cb46b0289 100644
--- a/src/libstd/sys/unix/mutex.rs
+++ b/src/libstd/sys/unix/mutex.rs
@@ -11,7 +11,6 @@
 use cell::UnsafeCell;
 use kinds::Sync;
 use sys::sync as ffi;
-use sys_common::mutex;
 
 pub struct Mutex { inner: UnsafeCell<ffi::pthread_mutex_t> }
 
@@ -26,6 +25,7 @@ pub const MUTEX_INIT: Mutex = Mutex {
 
 unsafe impl Sync for Mutex {}
 
+#[allow(dead_code)] // sys isn't exported yet
 impl Mutex {
     #[inline]
     pub unsafe fn new() -> Mutex {
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index cafe52f8403..446960ab92f 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -10,17 +10,16 @@
 
 //! Implementation of `std::os` functionality for unix systems
 
+#![allow(unused_imports)] // lots of cfg code here
+
 use prelude::*;
 
-use error::{FromError, Error};
-use fmt;
 use io::{IoError, IoResult};
-use libc::{mod, c_int, c_char, c_void};
+use libc::{mod, c_int, c_char};
+use os;
 use path::BytesContainer;
 use ptr;
-use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
 use sys::fs::FileDesc;
-use os;
 
 use os::TMPBUF_SZ;
 
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index 868b460aa5e..3b868065f8f 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -145,7 +145,7 @@ impl UnixStream {
     fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
         let ret = Guard {
             fd: self.fd(),
-            guard: unsafe { self.inner.lock.lock().unwrap() },
+            guard: self.inner.lock.lock().unwrap(),
         };
         assert!(set_nonblocking(self.fd(), true).is_ok());
         ret
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index 835f4279d9b..48df8c4eced 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -11,7 +11,7 @@ use self::Req::*;
 
 use libc::{mod, pid_t, c_void, c_int};
 use c_str::CString;
-use io::{mod, IoResult, IoError, EndOfFile};
+use io::{IoResult, EndOfFile};
 use mem;
 use os;
 use ptr;
@@ -327,7 +327,7 @@ impl Process {
         // The actual communication between the helper thread and this thread is
         // quite simple, just a channel moving data around.
 
-        unsafe { HELPER.boot(register_sigchld, waitpid_helper) }
+        HELPER.boot(register_sigchld, waitpid_helper);
 
         match self.try_wait() {
             Some(ret) => return Ok(ret),
@@ -335,7 +335,7 @@ impl Process {
         }
 
         let (tx, rx) = channel();
-        unsafe { HELPER.send(NewChild(self.pid, tx, deadline)); }
+        HELPER.send(NewChild(self.pid, tx, deadline));
         return match rx.recv_opt() {
             Ok(e) => Ok(e),
             Err(()) => Err(timeout("wait timed out")),
@@ -419,8 +419,15 @@ impl Process {
                             Ok(NewChild(pid, tx, deadline)) => {
                                 active.push((pid, tx, deadline));
                             }
+                            // Once we've been disconnected it means the main
+                            // thread is exiting (at_exit has run). We could
+                            // still have active waiter for other threads, so
+                            // we're just going to drop them all on the floor.
+                            // This means that they won't receive a "you're
+                            // done" message in which case they'll be considered
+                            // as timed out, but more generally errors will
+                            // start propagating.
                             Err(comm::Disconnected) => {
-                                assert!(active.len() == 0);
                                 break 'outer;
                             }
                             Err(comm::Empty) => break,
diff --git a/src/libstd/sys/unix/rwlock.rs b/src/libstd/sys/unix/rwlock.rs
index 0d63ff14ff2..4f9b06685ec 100644
--- a/src/libstd/sys/unix/rwlock.rs
+++ b/src/libstd/sys/unix/rwlock.rs
@@ -17,6 +17,7 @@ pub const RWLOCK_INIT: RWLock = RWLock {
     inner: UnsafeCell { value: ffi::PTHREAD_RWLOCK_INITIALIZER },
 };
 
+#[allow(dead_code)] // sys isn't exported yet
 impl RWLock {
     #[inline]
     pub unsafe fn new() -> RWLock {
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index bcbbb8766b7..f1d7f1784d0 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -34,7 +34,6 @@ impl Drop for Handler {
 
 #[cfg(any(target_os = "linux", target_os = "macos"))]
 mod imp {
-    use core::prelude::*;
     use sys_common::stack;
 
     use super::Handler;
diff --git a/src/libstd/sys/unix/tcp.rs b/src/libstd/sys/unix/tcp.rs
index e2a78947e16..696d3fb676d 100644
--- a/src/libstd/sys/unix/tcp.rs
+++ b/src/libstd/sys/unix/tcp.rs
@@ -135,10 +135,6 @@ impl TcpAcceptor {
         Err(sys_common::eof())
     }
 
-    pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        net::sockname(self.fd(), libc::getsockname)
-    }
-
     pub fn set_timeout(&mut self, timeout: Option<u64>) {
         self.deadline = timeout.map(|a| sys::timer::now() + a).unwrap_or(0);
     }
diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs
index fe393b81e3d..1ababbc0d85 100644
--- a/src/libstd/sys/unix/timer.rs
+++ b/src/libstd/sys/unix/timer.rs
@@ -100,7 +100,7 @@ pub fn now() -> u64 {
 fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
     let mut set: c::fd_set = unsafe { mem::zeroed() };
 
-    let mut fd = FileDesc::new(input, true);
+    let fd = FileDesc::new(input, true);
     let mut timeout: libc::timeval = unsafe { mem::zeroed() };
 
     // active timers are those which are able to be selected upon (and it's a
@@ -168,8 +168,15 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
             1 => {
                 loop {
                     match messages.try_recv() {
+                        // Once we've been disconnected it means the main thread
+                        // is exiting (at_exit has run). We could still have
+                        // active timers for other threads, so we're just going
+                        // to drop them all on the floor. This is all we can
+                        // really do, however, to prevent resource leakage. The
+                        // remaining timers will likely start panicking quickly
+                        // as they attempt to re-use this thread but are
+                        // disallowed to do so.
                         Err(comm::Disconnected) => {
-                            assert!(active.len() == 0);
                             break 'outer;
                         }
 
diff --git a/src/libstd/sys/unix/tty.rs b/src/libstd/sys/unix/tty.rs
index 28c17fd4966..d05047a220f 100644
--- a/src/libstd/sys/unix/tty.rs
+++ b/src/libstd/sys/unix/tty.rs
@@ -43,5 +43,4 @@ impl TTY {
     pub fn get_winsize(&mut self) -> IoResult<(int, int)> {
         Err(sys_common::unimpl())
     }
-    pub fn isatty(&self) -> bool { false }
 }
diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs
index 42c8f7705e1..e5a37e5651b 100644
--- a/src/libstd/sys/windows/backtrace.rs
+++ b/src/libstd/sys/windows/backtrace.rs
@@ -7,19 +7,22 @@
 // <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.
-/// As always, windows has something very different than unix, we mainly want
-/// to avoid having to depend too much on libunwind for windows.
-///
-/// If you google around, you'll find a fair bit of references to built-in
-/// functions to get backtraces on windows. It turns out that most of these are
-/// in an external library called dbghelp. I was unable to find this library
-/// via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
-/// of it.
-///
-/// You'll also find that there's a function called CaptureStackBackTrace
-/// mentioned frequently (which is also easy to use), but sadly I didn't have a
-/// copy of that function in my mingw install (maybe it was broken?). Instead,
-/// this takes the route of using StackWalk64 in order to walk the stack.
+
+//! As always, windows has something very different than unix, we mainly want
+//! to avoid having to depend too much on libunwind for windows.
+//!
+//! If you google around, you'll find a fair bit of references to built-in
+//! functions to get backtraces on windows. It turns out that most of these are
+//! in an external library called dbghelp. I was unable to find this library
+//! via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
+//! of it.
+//!
+//! You'll also find that there's a function called CaptureStackBackTrace
+//! mentioned frequently (which is also easy to use), but sadly I didn't have a
+//! copy of that function in my mingw install (maybe it was broken?). Instead,
+//! this takes the route of using StackWalk64 in order to walk the stack.
+
+#![allow(dead_code)] // constants/fields aren't always used on all platforms
 
 use c_str::CString;
 use intrinsics;
@@ -294,7 +297,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> {
     // According to windows documentation, all dbghelp functions are
     // single-threaded.
     static LOCK: StaticMutex = MUTEX_INIT;
-    let _g = unsafe { LOCK.lock() };
+    let _g = LOCK.lock();
 
     // Open up dbghelp.dll, we don't link to it explicitly because it can't
     // always be found. Additionally, it's nice having fewer dependencies.
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 06259d61fcb..0aa7e539d78 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -15,7 +15,6 @@
 #![allow(non_camel_case_types)]
 
 use libc;
-use prelude::*;
 
 pub const WSADESCRIPTION_LEN: uint = 256;
 pub const WSASYS_STATUS_LEN: uint = 128;
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 3ad439078b9..523d9e9a3c2 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -10,21 +10,17 @@
 
 //! Blocking Windows-based file I/O
 
-use alloc::arc::Arc;
 use libc::{mod, c_int};
 
-use c_str::CString;
+use io;
 use mem;
-use sys::os::fill_utf16_buf_and_decode;
-use path;
 use ptr;
-use str;
-use io;
+use sys::os::fill_utf16_buf_and_decode;
 
 use prelude::*;
 use sys;
 use sys::os;
-use sys_common::{keep_going, eof, mkerr_libc};
+use sys_common::{unimpl, mkerr_libc};
 
 use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
 use io::{IoResult, IoError, FileStat, SeekStyle};
@@ -445,7 +441,7 @@ pub fn stat(p: &Path) -> IoResult<FileStat> {
 // FIXME: move this to platform-specific modules (for now)?
 pub fn lstat(_p: &Path) -> IoResult<FileStat> {
     // FIXME: implementation is missing
-    Err(super::unimpl())
+    Err(unimpl())
 }
 
 pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> {
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index aee98e22836..15dc075cef9 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -11,30 +11,14 @@
 #![allow(missing_docs)]
 #![allow(non_camel_case_types)]
 #![allow(non_snake_case)]
-#![allow(unused_imports)]
-#![allow(dead_code)]
-#![allow(unused_unsafe)]
-#![allow(unused_mut)]
 
 extern crate libc;
 
-use num;
 use mem;
 use prelude::*;
 use io::{mod, IoResult, IoError};
 use sync::{Once, ONCE_INIT};
 
-macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
-    static $name: Helper<$m> = Helper {
-        lock: ::sync::MUTEX_INIT,
-        cond: ::sync::CONDVAR_INIT,
-        chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
-        signal: ::cell::UnsafeCell { value: 0 },
-        initialized: ::cell::UnsafeCell { value: false },
-        shutdown: ::cell::UnsafeCell { value: false },
-    };
-) }
-
 pub mod backtrace;
 pub mod c;
 pub mod ext;
@@ -179,14 +163,6 @@ pub fn init_net() {
     }
 }
 
-pub fn unimpl() -> IoError {
-    IoError {
-        kind: io::IoUnavailable,
-        desc: "operation is not implemented",
-        detail: None,
-    }
-}
-
 pub fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> {
     match s {
         Some(s) => Ok({
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index fa08290a888..5a7be63e39f 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -15,14 +15,12 @@
 
 use prelude::*;
 
-use fmt;
 use io::{IoResult, IoError};
-use libc::{c_int, c_char, c_void};
+use libc::{c_int, c_void};
 use libc;
 use os;
 use path::BytesContainer;
 use ptr;
-use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
 use sys::fs::FileDesc;
 use slice;
 
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index fc3640f2604..8b2fc3d9fb5 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -365,7 +365,7 @@ impl UnixStream {
         // acquire the lock.
         //
         // See comments in close_read() about why this lock is necessary.
-        let guard = unsafe { self.inner.lock.lock() };
+        let guard = self.inner.lock.lock();
         if self.read_closed() {
             return Err(eof())
         }
@@ -441,7 +441,7 @@ impl UnixStream {
             // going after we woke up.
             //
             // See comments in close_read() about why this lock is necessary.
-            let guard = unsafe { self.inner.lock.lock() };
+            let guard = self.inner.lock.lock();
             if self.write_closed() {
                 return Err(epipe())
             }
@@ -516,14 +516,14 @@ impl UnixStream {
         // close_read() between steps 1 and 2. By atomically executing steps 1
         // and 2 with a lock with respect to close_read(), we're guaranteed that
         // no thread will erroneously sit in a read forever.
-        let _guard = unsafe { self.inner.lock.lock() };
+        let _guard = self.inner.lock.lock();
         self.inner.read_closed.store(true, atomic::SeqCst);
         self.cancel_io()
     }
 
     pub fn close_write(&mut self) -> IoResult<()> {
         // see comments in close_read() for why this lock is necessary
-        let _guard = unsafe { self.inner.lock.lock() };
+        let _guard = self.inner.lock.lock();
         self.inner.write_closed.store(true, atomic::SeqCst);
         self.cancel_io()
     }
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 0c2c76077dd..0c5a0eb6bb9 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -8,25 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use libc::{pid_t, c_void, c_int};
+use prelude::*;
+
+use libc::{pid_t, c_void};
 use libc;
 use c_str::CString;
 use io;
 use mem;
 use os;
 use ptr;
-use prelude::*;
-use io::process::{ProcessExit, ExitStatus, ExitSignal};
+use io::process::{ProcessExit, ExitStatus};
 use collections;
 use path::BytesContainer;
 use hash::Hash;
 use io::{IoResult, IoError};
 
-use sys::fs;
-use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
+use sys::timer;
 use sys::fs::FileDesc;
-use sys_common::helper_thread::Helper;
-use sys_common::{AsInner, mkerr_libc, timeout};
+use sys_common::{AsInner, timeout};
 
 use io::fs::PathExtensions;
 
@@ -121,8 +120,6 @@ impl Process {
         use libc::funcs::extra::msvcrt::get_osfhandle;
 
         use mem;
-        use iter::{Iterator, IteratorExt};
-        use str::StrExt;
 
         if cfg.gid().is_some() || cfg.uid().is_some() {
             return Err(IoError {
diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs
index bdf2e0bccb1..ab092f5a243 100644
--- a/src/libstd/sys/windows/stack_overflow.rs
+++ b/src/libstd/sys/windows/stack_overflow.rs
@@ -14,7 +14,7 @@ use ptr;
 use mem;
 use libc;
 use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
-use sys_common::{stack, thread_info};
+use sys_common::stack;
 
 pub struct Handler {
     _data: *mut libc::c_void
@@ -30,14 +30,6 @@ impl Drop for Handler {
     fn drop(&mut self) {}
 }
 
-// get_task_info is called from an exception / signal handler.
-// It returns the guard page of the current task or 0 if that
-// guard page doesn't exist. None is returned if there's currently
-// no local task.
-unsafe fn get_task_guard_page() -> uint {
-    thread_info::stack_guard()
-}
-
 // This is initialized in init() and only read from after
 static mut PAGE_SIZE: uint = 0;
 
diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs
index 513c1d38e36..339c724d9a9 100644
--- a/src/libstd/sys/windows/tcp.rs
+++ b/src/libstd/sys/windows/tcp.rs
@@ -14,11 +14,10 @@ use libc;
 use mem;
 use ptr;
 use prelude::*;
-use super::{last_error, last_net_error, retry, sock_t};
+use super::{last_error, last_net_error, sock_t};
 use sync::{Arc, atomic};
-use sys::fs::FileDesc;
 use sys::{mod, c, set_nonblocking, wouldblock, timer};
-use sys_common::{mod, timeout, eof, net};
+use sys_common::{timeout, eof, net};
 
 pub use sys_common::net::TcpStream;
 
@@ -205,10 +204,6 @@ impl TcpAcceptor {
         Err(eof())
     }
 
-    pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        net::sockname(self.socket(), libc::getsockname)
-    }
-
     pub fn set_timeout(&mut self, timeout: Option<u64>) {
         self.deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
     }
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index 4498f56c00a..59ab5f5c4d9 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use core::prelude::*;
-
 use boxed::Box;
 use cmp;
 use mem;
diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs
index 60b0d584db3..4ac57e37117 100644
--- a/src/libstd/sys/windows/thread_local.rs
+++ b/src/libstd/sys/windows/thread_local.rs
@@ -137,9 +137,9 @@ unsafe fn init_dtors() {
     rt::at_exit(move|| {
         DTOR_LOCK.lock();
         let dtors = DTORS;
-        DTORS = 0 as *mut _;
+        DTORS = 1 as *mut _;
         mem::transmute::<_, Box<Vec<(Key, Dtor)>>>(dtors);
-        assert!(DTORS.is_null()); // can't re-init after destructing
+        assert!(DTORS as uint == 1); // can't re-init after destructing
         DTOR_LOCK.unlock();
     });
 }
@@ -147,6 +147,9 @@ unsafe fn init_dtors() {
 unsafe fn register_dtor(key: Key, dtor: Dtor) {
     DTOR_LOCK.lock();
     init_dtors();
+    assert!(DTORS as uint != 0);
+    assert!(DTORS as uint != 1,
+            "cannot create new TLS keys after the main thread has exited");
     (*DTORS).push((key, dtor));
     DTOR_LOCK.unlock();
 }
@@ -154,6 +157,9 @@ unsafe fn register_dtor(key: Key, dtor: Dtor) {
 unsafe fn unregister_dtor(key: Key) -> bool {
     DTOR_LOCK.lock();
     init_dtors();
+    assert!(DTORS as uint != 0);
+    assert!(DTORS as uint != 1,
+            "cannot unregister destructors after the main thread has exited");
     let ret = {
         let dtors = &mut *DTORS;
         let before = dtors.len();
@@ -232,6 +238,7 @@ unsafe extern "system" fn on_tls_callback(h: LPVOID,
     }
 }
 
+#[allow(dead_code)] // not actually dead
 unsafe fn run_dtors() {
     let mut any_run = true;
     for _ in range(0, 5i) {
diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs
index 874838950cd..c0e67642a64 100644
--- a/src/libstd/sys/windows/timer.rs
+++ b/src/libstd/sys/windows/timer.rs
@@ -26,8 +26,6 @@ use libc;
 use ptr;
 use comm;
 
-use sys::c;
-use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
 use prelude::*;
 use io::IoResult;
@@ -80,9 +78,10 @@ fn helper(input: libc::HANDLE, messages: Receiver<Req>, _: ()) {
                             None => {}
                         }
                     }
+                    // See the comment in unix::timer for why we don't have any
+                    // asserts here and why we're likely just leaving timers on
+                    // the floor as we exit.
                     Err(comm::Disconnected) => {
-                        assert_eq!(objs.len(), 1);
-                        assert_eq!(chans.len(), 0);
                         break 'outer;
                     }
                     Err(..) => break
diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs
index 99292b3b44b..607bb05f54f 100644
--- a/src/libstd/sys/windows/tty.rs
+++ b/src/libstd/sys/windows/tty.rs
@@ -26,7 +26,6 @@
 //! to working in raw UTF-16, with such a wrapper around it.
 
 use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode};
-use super::c::{ERROR_ILLEGAL_CHARACTER};
 use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS};
 use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT};
 use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE};
@@ -38,6 +37,8 @@ use prelude::*;
 use ptr;
 use str::from_utf8;
 
+use sys_common::unimpl;
+
 fn invalid_encoding() -> IoError {
     IoError {
         kind: io::InvalidInput,
@@ -149,11 +150,8 @@ impl TTY {
         // Make a CONSOLE_SCREEN_BUFFER_INFO
         // Call GetConsoleScreenBufferInfo
         // Maybe call GetLargestConsoleWindowSize instead?
-        Err(super::unimpl())
+        Err(unimpl())
     }
-
-    // Let us magically declare this as a TTY
-    pub fn isatty(&self) -> bool { true }
 }
 
 impl Drop for TTY {