From 1b56a8b600d5ec22ae2eb07a6e2333ee0b6c2017 Mon Sep 17 00:00:00 2001 From: Zejun Zhao Date: Mon, 16 Dec 2024 11:32:37 +0800 Subject: [PATCH] Enable syscall restart --- kernel/src/syscall/accept.rs | 6 +++++- kernel/src/syscall/connect.rs | 8 +++++++- kernel/src/syscall/fcntl.rs | 5 ++++- kernel/src/syscall/flock.rs | 7 ++++++- kernel/src/syscall/futex.rs | 11 ++++------- kernel/src/syscall/ioctl.rs | 1 + kernel/src/syscall/open.rs | 6 +++++- kernel/src/syscall/read.rs | 26 ++++++++++++++++---------- kernel/src/syscall/recvfrom.rs | 9 ++++++++- kernel/src/syscall/recvmsg.rs | 8 +++++++- kernel/src/syscall/sendmsg.rs | 8 +++++++- kernel/src/syscall/sendto.rs | 8 +++++++- kernel/src/syscall/wait4.rs | 6 +++++- kernel/src/syscall/waitid.rs | 6 +++++- kernel/src/syscall/write.rs | 26 ++++++++++++++++---------- 15 files changed, 103 insertions(+), 38 deletions(-) diff --git a/kernel/src/syscall/accept.rs b/kernel/src/syscall/accept.rs index a52751bb2..2a6c74357 100644 --- a/kernel/src/syscall/accept.rs +++ b/kernel/src/syscall/accept.rs @@ -49,7 +49,11 @@ fn do_accept( ) -> Result { let (connected_socket, socket_addr) = { let socket = get_socket_from_fd(sockfd)?; - socket.accept()? + socket.accept().map_err(|err| match err.error() { + // FIXME: `accept` should not be restarted if a timeout has been set on the socket using `setsockopt`. + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })? }; if flags.contains(Flags::SOCK_NONBLOCK) { diff --git a/kernel/src/syscall/connect.rs b/kernel/src/syscall/connect.rs index e487c6a65..75f5a941b 100644 --- a/kernel/src/syscall/connect.rs +++ b/kernel/src/syscall/connect.rs @@ -17,6 +17,12 @@ pub fn sys_connect( debug!("fd = {sockfd}, socket_addr = {socket_addr:?}"); let socket = get_socket_from_fd(sockfd)?; - socket.connect(socket_addr)?; + socket + .connect(socket_addr) + .map_err(|err| match err.error() { + // FIXME: `connect` should not be restarted if a timeout has been set on the socket using `setsockopt`. + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })?; Ok(SyscallReturn::Return(0)) } diff --git a/kernel/src/syscall/fcntl.rs b/kernel/src/syscall/fcntl.rs index 29a3059cc..9bf13b3f8 100644 --- a/kernel/src/syscall/fcntl.rs +++ b/kernel/src/syscall/fcntl.rs @@ -26,7 +26,10 @@ pub fn sys_fcntl(fd: FileDesc, cmd: i32, arg: u64, ctx: &Context) -> Result handle_setfl(fd, arg, ctx), FcntlCmd::F_GETLK => handle_getlk(fd, arg, ctx), FcntlCmd::F_SETLK => handle_setlk(fd, arg, true, ctx), - FcntlCmd::F_SETLKW => handle_setlk(fd, arg, false, ctx), + FcntlCmd::F_SETLKW => handle_setlk(fd, arg, false, ctx).map_err(|err| match err.error() { + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + }), FcntlCmd::F_GETOWN => handle_getown(fd, ctx), FcntlCmd::F_SETOWN => handle_setown(fd, arg, ctx), } diff --git a/kernel/src/syscall/flock.rs b/kernel/src/syscall/flock.rs index 877367fec..b1989a6f9 100644 --- a/kernel/src/syscall/flock.rs +++ b/kernel/src/syscall/flock.rs @@ -30,7 +30,12 @@ pub fn sys_flock(fd: FileDesc, ops: i32, ctx: &Context) -> Result let type_ = FlockType::from(ops); FlockItem::new(&file, type_) }; - inode_file.set_flock(flock, is_nonblocking)?; + inode_file + .set_flock(flock, is_nonblocking) + .map_err(|err| match err.error() { + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })?; } Ok(SyscallReturn::Return(0)) } diff --git a/kernel/src/syscall/futex.rs b/kernel/src/syscall/futex.rs index b8497f849..7299e227d 100644 --- a/kernel/src/syscall/futex.rs +++ b/kernel/src/syscall/futex.rs @@ -136,13 +136,10 @@ pub fn sys_futex( return_errno_with_message!(Errno::EINVAL, "unsupported futex op"); } } - .map_err(|e| { - // From Linux manual, Futex returns `ETIMEDOUT` instead of `ETIME` - if e.error() == Errno::ETIME { - Error::with_message(Errno::ETIMEDOUT, "futex wait timeout") - } else { - e - } + .map_err(|err| match err.error() { + Errno::ETIME => Error::new(Errno::ETIMEDOUT), + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, })?; debug!("futex returns, tid= {} ", ctx.posix_thread.tid()); diff --git a/kernel/src/syscall/ioctl.rs b/kernel/src/syscall/ioctl.rs index 6ce785370..0c461a4e7 100644 --- a/kernel/src/syscall/ioctl.rs +++ b/kernel/src/syscall/ioctl.rs @@ -56,6 +56,7 @@ pub fn sys_ioctl(fd: FileDesc, cmd: u32, arg: Vaddr, ctx: &Context) -> Result file.ioctl(ioctl_cmd, arg)?, }; Ok(SyscallReturn::Return(res as _)) diff --git a/kernel/src/syscall/open.rs b/kernel/src/syscall/open.rs index 6cee6c2a3..db0dcccf7 100644 --- a/kernel/src/syscall/open.rs +++ b/kernel/src/syscall/open.rs @@ -33,7 +33,11 @@ pub fn sys_openat( .fs() .resolver() .read() - .open(&fs_path, flags, mask_mode)?; + .open(&fs_path, flags, mask_mode) + .map_err(|err| match err.error() { + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })?; Arc::new(inode_handle) }; let mut file_table = current.file_table().lock(); diff --git a/kernel/src/syscall/read.rs b/kernel/src/syscall/read.rs index 182ec87a7..000d1b7a0 100644 --- a/kernel/src/syscall/read.rs +++ b/kernel/src/syscall/read.rs @@ -22,16 +22,22 @@ pub fn sys_read( // According to , if // the user specified an empty buffer, we should detect errors by checking // the file descriptor. If no errors detected, return 0 successfully. - let read_len = if buf_len != 0 { - let mut writer = ctx - .process - .root_vmar() - .vm_space() - .writer(user_buf_addr, buf_len)?; - file.read(&mut writer)? - } else { - file.read_bytes(&mut [])? - }; + let read_len = { + if buf_len != 0 { + let mut writer = ctx + .process + .root_vmar() + .vm_space() + .writer(user_buf_addr, buf_len)?; + file.read(&mut writer) + } else { + file.read_bytes(&mut []) + } + } + .map_err(|err| match err.error() { + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })?; Ok(SyscallReturn::Return(read_len as _)) } diff --git a/kernel/src/syscall/recvfrom.rs b/kernel/src/syscall/recvfrom.rs index 8b1bb0022..2f1525fee 100644 --- a/kernel/src/syscall/recvfrom.rs +++ b/kernel/src/syscall/recvfrom.rs @@ -27,7 +27,14 @@ pub fn sys_recvfrom( vm_space.writer(buf, len)? }; - let (recv_size, message_header) = socket.recvmsg(&mut writers, flags)?; + let (recv_size, message_header) = + socket + .recvmsg(&mut writers, flags) + .map_err(|err| match err.error() { + // FIXME: `recvfrom` should not be restarted if a timeout has been set on the socket using `setsockopt`. + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })?; if let Some(socket_addr) = message_header.addr() && src_addr != 0 diff --git a/kernel/src/syscall/recvmsg.rs b/kernel/src/syscall/recvmsg.rs index ec6b12e00..8440dafd0 100644 --- a/kernel/src/syscall/recvmsg.rs +++ b/kernel/src/syscall/recvmsg.rs @@ -25,7 +25,13 @@ pub fn sys_recvmsg( let (total_bytes, message_header) = { let socket = get_socket_from_fd(sockfd)?; let mut io_vec_writer = c_user_msghdr.copy_writer_array_from_user(ctx)?; - socket.recvmsg(&mut io_vec_writer, flags)? + socket + .recvmsg(&mut io_vec_writer, flags) + .map_err(|err| match err.error() { + // FIXME: `recvmsg` should not be restarted if a timeout has been set on the socket using `setsockopt`. + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })? }; if let Some(addr) = message_header.addr() { diff --git a/kernel/src/syscall/sendmsg.rs b/kernel/src/syscall/sendmsg.rs index 9b57d4728..b38b1883b 100644 --- a/kernel/src/syscall/sendmsg.rs +++ b/kernel/src/syscall/sendmsg.rs @@ -39,7 +39,13 @@ pub fn sys_sendmsg( (io_vec_reader, MessageHeader::new(addr, control_message)) }; - let total_bytes = socket.sendmsg(&mut io_vec_reader, message_header, flags)?; + let total_bytes = socket + .sendmsg(&mut io_vec_reader, message_header, flags) + .map_err(|err| match err.error() { + // FIXME: `sendmsg` should not be restarted if a timeout has been set on the socket using `setsockopt`. + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })?; Ok(SyscallReturn::Return(total_bytes as _)) } diff --git a/kernel/src/syscall/sendto.rs b/kernel/src/syscall/sendto.rs index 29f915732..84aac1197 100644 --- a/kernel/src/syscall/sendto.rs +++ b/kernel/src/syscall/sendto.rs @@ -34,7 +34,13 @@ pub fn sys_sendto( let vm_space = ctx.process.root_vmar().vm_space(); vm_space.reader(buf, len)? }; - let send_size = socket.sendmsg(&mut reader, message_header, flags)?; + let send_size = socket + .sendmsg(&mut reader, message_header, flags) + .map_err(|err| match err.error() { + // FIXME: `sendto` should not be restarted if a timeout has been set on the socket using `setsockopt`. + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })?; Ok(SyscallReturn::Return(send_size as _)) } diff --git a/kernel/src/syscall/wait4.rs b/kernel/src/syscall/wait4.rs index 5773d12bf..41aaca1d4 100644 --- a/kernel/src/syscall/wait4.rs +++ b/kernel/src/syscall/wait4.rs @@ -22,7 +22,11 @@ pub fn sys_wait4( debug!("wait4 current pid = {}", ctx.process.pid()); let process_filter = ProcessFilter::from_id(wait_pid as _); - let waited_process = wait_child_exit(process_filter, wait_options, ctx)?; + let waited_process = + wait_child_exit(process_filter, wait_options, ctx).map_err(|err| match err.error() { + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })?; let Some(process) = waited_process else { return Ok(SyscallReturn::Return(0 as _)); }; diff --git a/kernel/src/syscall/waitid.rs b/kernel/src/syscall/waitid.rs index d54c98796..b13c1d205 100644 --- a/kernel/src/syscall/waitid.rs +++ b/kernel/src/syscall/waitid.rs @@ -18,7 +18,11 @@ pub fn sys_waitid( let process_filter = ProcessFilter::from_which_and_id(which, upid)?; let wait_options = WaitOptions::from_bits(options as u32) .ok_or(Error::with_message(Errno::EINVAL, "invalid options"))?; - let waited_process = wait_child_exit(process_filter, wait_options, ctx)?; + let waited_process = + wait_child_exit(process_filter, wait_options, ctx).map_err(|err| match err.error() { + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })?; let pid = waited_process.map_or(0, |process| process.pid()); Ok(SyscallReturn::Return(pid as _)) } diff --git a/kernel/src/syscall/write.rs b/kernel/src/syscall/write.rs index 0eda4acd4..3799966f8 100644 --- a/kernel/src/syscall/write.rs +++ b/kernel/src/syscall/write.rs @@ -22,16 +22,22 @@ pub fn sys_write( // According to , if // the user specified an empty buffer, we should detect errors by checking // the file descriptor. If no errors detected, return 0 successfully. - let write_len = if user_buf_len != 0 { - let mut reader = ctx - .process - .root_vmar() - .vm_space() - .reader(user_buf_ptr, user_buf_len)?; - file.write(&mut reader)? - } else { - file.write_bytes(&[])? - }; + let write_len = { + if user_buf_len != 0 { + let mut reader = ctx + .process + .root_vmar() + .vm_space() + .reader(user_buf_ptr, user_buf_len)?; + file.write(&mut reader) + } else { + file.write_bytes(&[]) + } + } + .map_err(|err| match err.error() { + Errno::EINTR => Error::new(Errno::ERESTARTSYS), + _ => err, + })?; Ok(SyscallReturn::Return(write_len as _)) }