Skip to content

Commit 971462e

Browse files
committed
implement exceptfds partially for sys_pselect6 to fix arch bash and sh.
1 parent acf03d7 commit 971462e

1 file changed

Lines changed: 118 additions & 47 deletions

File tree

src/process/fd_table/select.rs

Lines changed: 118 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,17 @@ pub struct FdSet {
2424
}
2525

2626
impl FdSet {
27-
fn iter_fds(&self, max: i32) -> impl Iterator<Item = Fd> {
28-
let mut candidate_fd = 0;
27+
fn iter_fds(&self, max: usize) -> impl Iterator<Item = Fd> {
28+
let mut candidate_fd = 0usize;
2929

3030
iter::from_fn(move || {
3131
loop {
3232
if candidate_fd == max {
3333
return None;
3434
}
3535

36-
if self.set[candidate_fd as usize / 64] & (1 << (candidate_fd % 64)) != 0 {
37-
let ret = Fd(candidate_fd);
36+
if self.set[candidate_fd / 64] & (1 << (candidate_fd % 64)) != 0 {
37+
let ret = Fd(candidate_fd as i32);
3838
candidate_fd += 1;
3939

4040
return Some(ret);
@@ -58,71 +58,113 @@ impl FdSet {
5858

5959
unsafe impl UserCopyable for FdSet {}
6060

61-
// TODO: handle exceptfds
61+
#[repr(C)]
62+
#[derive(Clone, Copy, Debug)]
63+
pub(crate) struct PSelect6SigMask {
64+
sigmask: TUA<SigSet>,
65+
sigsetsize: usize,
66+
}
67+
68+
unsafe impl UserCopyable for PSelect6SigMask {}
69+
70+
// TODO: handle exceptfds readiness semantics.
6271
pub async fn sys_pselect6(
6372
ctx: &ProcessCtx,
6473
max: i32,
6574
readfds: TUA<FdSet>,
6675
writefds: TUA<FdSet>,
67-
_exceptfds: TUA<FdSet>,
76+
exceptfds: TUA<FdSet>,
6877
timeout: TUA<TimeSpec>,
69-
mask: TUA<SigSet>,
78+
mask: TUA<PSelect6SigMask>,
7079
) -> Result<usize> {
80+
if max < 0 || max as usize > SET_SIZE {
81+
return Err(KernelError::InvalidValue);
82+
}
83+
84+
let max = max as usize;
7185
let task = ctx.shared();
7286

73-
let mut read_fd_set = copy_from_user(readfds).await?;
87+
let mut read_fd_set = if readfds.is_null() {
88+
None
89+
} else {
90+
Some(copy_from_user(readfds).await?)
91+
};
7492

7593
let mut read_fds = Vec::new();
7694

77-
let mut write_fd_set = copy_from_user(writefds).await?;
95+
let mut write_fd_set = if writefds.is_null() {
96+
None
97+
} else {
98+
Some(copy_from_user(writefds).await?)
99+
};
78100

79101
let mut write_fds = Vec::new();
80102

103+
let mut except_fd_set = if exceptfds.is_null() {
104+
None
105+
} else {
106+
Some(copy_from_user(exceptfds).await?)
107+
};
108+
81109
let mut timeout_fut = if timeout.is_null() {
82110
None
83111
} else {
84112
let duration = copy_from_user(timeout).await?.into();
85113
Some(pin!(sleep(duration)))
86114
};
87115

88-
for fd in read_fd_set.iter_fds(max) {
89-
let file = task
90-
.fd_table
91-
.lock_save_irq()
92-
.get(fd)
93-
.ok_or(KernelError::BadFd)?;
94-
95-
read_fds.push((
96-
Box::pin(async move {
97-
let (ops, _) = &mut *file.lock().await;
98-
99-
ops.poll_read_ready().await
100-
}),
101-
fd,
102-
));
116+
if let Some(ref read_fd_set) = read_fd_set {
117+
for fd in read_fd_set.iter_fds(max) {
118+
let file = task
119+
.fd_table
120+
.lock_save_irq()
121+
.get(fd)
122+
.ok_or(KernelError::BadFd)?;
123+
124+
read_fds.push((
125+
Box::pin(async move {
126+
let (ops, _) = &mut *file.lock().await;
127+
128+
ops.poll_read_ready().await
129+
}),
130+
fd,
131+
));
132+
}
103133
}
104134

105-
for fd in write_fd_set.iter_fds(max) {
106-
let file = task
107-
.fd_table
108-
.lock_save_irq()
109-
.get(fd)
110-
.ok_or(KernelError::BadFd)?;
111-
112-
write_fds.push((
113-
Box::pin(async move {
114-
let (ops, _) = &mut *file.lock().await;
115-
116-
ops.poll_write_ready().await
117-
}),
118-
fd,
119-
));
135+
if let Some(ref write_fd_set) = write_fd_set {
136+
for fd in write_fd_set.iter_fds(max) {
137+
let file = task
138+
.fd_table
139+
.lock_save_irq()
140+
.get(fd)
141+
.ok_or(KernelError::BadFd)?;
142+
143+
write_fds.push((
144+
Box::pin(async move {
145+
let (ops, _) = &mut *file.lock().await;
146+
147+
ops.poll_write_ready().await
148+
}),
149+
fd,
150+
));
151+
}
120152
}
121153

122154
let mask = if mask.is_null() {
123155
None
124156
} else {
125-
Some(copy_from_user(mask).await?)
157+
let args: PSelect6SigMask = copy_from_user(mask).await?;
158+
159+
if args.sigsetsize != core::mem::size_of::<SigSet>() {
160+
return Err(KernelError::InvalidValue);
161+
}
162+
163+
if args.sigmask.is_null() {
164+
None
165+
} else {
166+
Some(copy_from_user(args.sigmask).await?)
167+
}
126168
};
127169
let old_sigmask = task.sig_mask.load();
128170
if let Some(mask) = mask {
@@ -131,24 +173,35 @@ pub async fn sys_pselect6(
131173
task.sig_mask.store(new_sigmask);
132174
}
133175

134-
read_fd_set.zero();
135-
write_fd_set.zero();
176+
if let Some(ref mut read_fd_set) = read_fd_set {
177+
read_fd_set.zero();
178+
}
179+
if let Some(ref mut write_fd_set) = write_fd_set {
180+
write_fd_set.zero();
181+
}
182+
if let Some(ref mut except_fd_set) = except_fd_set {
183+
except_fd_set.zero();
184+
}
136185

137186
let n = poll_fn(|cx| {
138187
let mut num_ready: usize = 0;
139188

140189
for (fut, fd) in read_fds.iter_mut() {
141190
if fut.as_mut().poll(cx).is_ready() {
142191
// Mark the is_ready bool. Don't break out of the loop just
143-
// yet, we may aswell check all fds while we're here.
144-
read_fd_set.set_fd(*fd);
192+
// yet, we may as well check all fds while we're here.
193+
if let Some(ref mut read_fd_set) = read_fd_set {
194+
read_fd_set.set_fd(*fd);
195+
}
145196
num_ready += 1;
146197
}
147198
}
148199

149200
for (fut, fd) in write_fds.iter_mut() {
150201
if fut.as_mut().poll(cx).is_ready() {
151-
write_fd_set.set_fd(*fd);
202+
if let Some(ref mut write_fd_set) = write_fd_set {
203+
write_fd_set.set_fd(*fd);
204+
}
152205
num_ready += 1;
153206
}
154207
}
@@ -166,12 +219,30 @@ pub async fn sys_pselect6(
166219
})
167220
.await;
168221

169-
copy_to_user(readfds, read_fd_set).await?;
170-
copy_to_user(writefds, write_fd_set).await?;
222+
let readfds_copy_result = if let Some(read_fd_set) = read_fd_set {
223+
copy_to_user(readfds, read_fd_set).await
224+
} else {
225+
Ok(())
226+
};
227+
let writefds_copy_result = if let Some(write_fd_set) = write_fd_set {
228+
copy_to_user(writefds, write_fd_set).await
229+
} else {
230+
Ok(())
231+
};
232+
let exceptfds_copy_result = if let Some(except_fd_set) = except_fd_set {
233+
copy_to_user(exceptfds, except_fd_set).await
234+
} else {
235+
Ok(())
236+
};
237+
171238
if mask.is_some() {
172239
task.sig_mask.store(old_sigmask);
173240
}
174241

242+
readfds_copy_result?;
243+
writefds_copy_result?;
244+
exceptfds_copy_result?;
245+
175246
Ok(n)
176247
}
177248

0 commit comments

Comments
 (0)