Skip to content

Commit

Permalink
Unix: Close the fd on ChannelClosed
Browse files Browse the repository at this point in the history
For unix OSes make sure to close the file descriptor on ChannelClosed.
The file descriptors should be closed in select to avoid leaking fds
after removal from pollfds (servo#96). After e06edbc this is safe and
avoids the previously seen race condition due to file descriptor
reuse.
  • Loading branch information
dlrobertson committed Nov 10, 2016
1 parent e06edbc commit 2e1081c
Showing 1 changed file with 11 additions and 8 deletions.
19 changes: 11 additions & 8 deletions src/platform/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use libc::{SO_LINGER, S_IFMT, S_IFSOCK, c_char, c_int, c_void, getsockopt};
use libc::{iovec, mkstemp, mode_t, msghdr, nfds_t, off_t, poll, pollfd, recvmsg, sendmsg};
use libc::{setsockopt, size_t, sockaddr, sockaddr_un, socketpair, socklen_t, sa_family_t};
use std::cmp;
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::fmt::{self, Debug, Formatter};
use std::hash::BuildHasherDefault;
Expand Down Expand Up @@ -453,7 +453,6 @@ impl OsIpcReceiverSet {
return Err(UnixError::last())
}

let mut hangups = HashSet::new();
for pollfd in self.pollfds.iter_mut() {
if (pollfd.revents & POLLIN) != 0 {
match recv(pollfd.fd, BlockingMode::Blocking) {
Expand All @@ -465,19 +464,23 @@ impl OsIpcReceiverSet {
shared_memory_regions));
}
Err(err) if err.channel_is_closed() => {
hangups.insert(pollfd.fd);
selection_results.push(OsIpcSelectionResult::ChannelClosed(
*self.fdids.get(&pollfd.fd).unwrap()))
let id = self.fdids.remove(&pollfd.fd).unwrap();
unsafe {
libc::close(pollfd.fd);
}
selection_results.push(OsIpcSelectionResult::ChannelClosed(id))
}
Err(err) => return Err(err),
}
pollfd.revents = pollfd.revents & !POLLIN
}
}

if !hangups.is_empty() {
self.pollfds.retain(|pollfd| !hangups.contains(&pollfd.fd));
}
// File descriptors not in fdids are closed channels, and the descriptor
// has been closed. This must be done after we have finished iterating over
// the pollfds vec.
let fdids = &self.fdids;
self.pollfds.retain(|pollfd| fdids.contains_key(&pollfd.fd));

Ok(selection_results)
}
Expand Down

0 comments on commit 2e1081c

Please sign in to comment.