(
nfds: i32,
readfds: Option<&mut [FdSetElement]>,
writefds: Option<&mut [FdSetElement]>,
exceptfds: Option<&mut [FdSetElement]>,
timeout: Option<&crate::timespec::Timespec>,
)
| 105 | } |
| 106 | |
| 107 | pub(crate) unsafe fn select( |
| 108 | nfds: i32, |
| 109 | readfds: Option<&mut [FdSetElement]>, |
| 110 | writefds: Option<&mut [FdSetElement]>, |
| 111 | exceptfds: Option<&mut [FdSetElement]>, |
| 112 | timeout: Option<&crate::timespec::Timespec>, |
| 113 | ) -> io::Result<i32> { |
| 114 | let len = crate::event::fd_set_num_elements_for_bitvector(nfds); |
| 115 | |
| 116 | let readfds = match readfds { |
| 117 | Some(readfds) => { |
| 118 | assert!(readfds.len() >= len); |
| 119 | readfds.as_mut_ptr() |
| 120 | } |
| 121 | None => null_mut(), |
| 122 | }; |
| 123 | let writefds = match writefds { |
| 124 | Some(writefds) => { |
| 125 | assert!(writefds.len() >= len); |
| 126 | writefds.as_mut_ptr() |
| 127 | } |
| 128 | None => null_mut(), |
| 129 | }; |
| 130 | let exceptfds = match exceptfds { |
| 131 | Some(exceptfds) => { |
| 132 | assert!(exceptfds.len() >= len); |
| 133 | exceptfds.as_mut_ptr() |
| 134 | } |
| 135 | None => null_mut(), |
| 136 | }; |
| 137 | |
| 138 | #[cfg(target_pointer_width = "32")] |
| 139 | { |
| 140 | // If we don't have Linux 5.1, and the timeout fits in a |
| 141 | // `__kernel_old_timespec`, use plain `pselect6`. |
| 142 | // |
| 143 | // We do this unconditionally, rather than trying `pselect6_time64` and |
| 144 | // falling back on `Errno::NOSYS`, because seccomp configurations will |
| 145 | // sometimes abort the process on syscalls they don't recognize. |
| 146 | #[cfg(not(feature = "linux_5_1"))] |
| 147 | { |
| 148 | use linux_raw_sys::general::__kernel_old_timespec; |
| 149 | |
| 150 | // If we don't have a timeout, or if we can convert the timeout to |
| 151 | // a `__kernel_old_timespec`, the use `__NR_pselect6`. |
| 152 | fn convert(timeout: &Timespec) -> Option<__kernel_old_timespec> { |
| 153 | Some(__kernel_old_timespec { |
| 154 | tv_sec: timeout.tv_sec.try_into().ok()?, |
| 155 | tv_nsec: timeout.tv_nsec.try_into().ok()?, |
| 156 | }) |
| 157 | } |
| 158 | let old_timeout = if let Some(timeout) = timeout { |
| 159 | match convert(timeout) { |
| 160 | // Could not convert timeout. |
| 161 | None => None, |
| 162 | // Could convert timeout. Ok! |
| 163 | Some(old_timeout) => Some(Some(old_timeout)), |
| 164 | } |
nothing calls this directly
no test coverage detected