Skip to content

Commit 2883f5c

Browse files
committed
Fix Selector::try_clone
Calls fcntl F_DUPFD_CLOEXEC expects two arguments; the command (F_DUPFD_CLOEXEC) and an argument for the command. In this case an lower bound for the resulting file descriptor. Because we didn't provide a value it would take whatever value was left in the register from whatever code used it before the system call. This caused Waker::new to fail, see issue #1497.
1 parent 7adfb75 commit 2883f5c

File tree

3 files changed

+12
-2
lines changed

3 files changed

+12
-2
lines changed

src/sys/unix/selector/epoll.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl Selector {
4141
}
4242

4343
pub fn try_clone(&self) -> io::Result<Selector> {
44-
syscall!(fcntl(self.ep, libc::F_DUPFD_CLOEXEC)).map(|ep| Selector {
44+
syscall!(fcntl(self.ep, libc::F_DUPFD_CLOEXEC, super::LOWEST_FD)).map(|ep| Selector {
4545
// It's the same selector, so we use the same id.
4646
#[cfg(debug_assertions)]
4747
id: self.id,

src/sys/unix/selector/kqueue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl Selector {
8787
}
8888

8989
pub fn try_clone(&self) -> io::Result<Selector> {
90-
syscall!(fcntl(self.kq, libc::F_DUPFD_CLOEXEC)).map(|kq| Selector {
90+
syscall!(fcntl(self.kq, libc::F_DUPFD_CLOEXEC, super::LOWEST_FD)).map(|kq| Selector {
9191
// It's the same selector, so we use the same id.
9292
#[cfg(debug_assertions)]
9393
id: self.id,

src/sys/unix/selector/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,13 @@ mod kqueue;
3333
target_os = "openbsd"
3434
))]
3535
pub(crate) use self::kqueue::{event, Event, Events, Selector};
36+
37+
/// Lowest file descriptor used in `Selector::try_clone`.
38+
///
39+
/// # Notes
40+
///
41+
/// Usually fds 0, 1 and 2 are standard in, out and error. Some application
42+
/// blindly assume this to be true, which means using any one of those a select
43+
/// could result in some interesting and unexpected errors. Avoid that by using
44+
/// an fd that doesn't have a pre-determined usage.
45+
const LOWEST_FD: libc::c_int = 3;

0 commit comments

Comments
 (0)