From 3754effab889d457af0c72932213fc606760f321 Mon Sep 17 00:00:00 2001 From: Akshit Gaur Date: Mon, 19 Jan 2026 12:47:20 +0530 Subject: [PATCH] Add shutdown syscall --- redox-rt/src/protocol.rs | 2 + src/platform/redox/socket.rs | 5 ++- tests/sys_socket/shutdown.c | 85 ++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 tests/sys_socket/shutdown.c diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 47f11215cf..d89f844953 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -63,6 +63,7 @@ pub enum SocketCall { Unbind = 6, GetToken = 7, GetPeerName = 8, + Shutdown = 9, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -117,6 +118,7 @@ impl SocketCall { 6 => Self::Unbind, 7 => Self::GetToken, 8 => Self::GetPeerName, + 9 => Self::Shutdown, _ => return None, }) } diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs index 836e1f09bb..d74ed1b88f 100644 --- a/src/platform/redox/socket.rs +++ b/src/platform/redox/socket.rs @@ -1024,8 +1024,9 @@ impl PalSocket for Sys { } fn shutdown(socket: c_int, how: c_int) -> Result<()> { - eprintln!("shutdown({}, {})", socket, how); - Err(Errno(ENOSYS)) + let metadata = [SocketCall::Shutdown as u64, how as u64]; + redox_rt::sys::sys_call(socket as usize, &mut [], CallFlags::empty(), &metadata)?; + Ok(()) } unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> Result { diff --git a/tests/sys_socket/shutdown.c b/tests/sys_socket/shutdown.c new file mode 100644 index 0000000000..9653633ddc --- /dev/null +++ b/tests/sys_socket/shutdown.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_helpers.h" + +int main(void) { + int sv[2]; + pid_t pid; + char buf[64]; + const char *parent_msg = "ping"; + const char *child_msg = "pong"; + + int status = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); + ERROR_IF(socketpair, status, == -1); + + pid = fork(); + ERROR_IF(fork, pid, == -1); + + if (pid == 0) { + close(sv[0]); + + memset(buf, 0, sizeof(buf)); + ssize_t n = recv(sv[1], buf, sizeof(buf), 0); + ERROR_IF(recv, n, == -1); + printf("child: received '%s'\n", buf); + + n = recv(sv[1], buf, sizeof(buf), 0); + if (n != 0) { + fprintf( + stderr, + "FAILURE: Expected EOF (0) after parent shutdown, got %ld\n", + (long)n); + exit(EXIT_FAILURE); + } + printf("child: verified EOF from parent (SHUT_WR worked)\n"); + + status = send(sv[1], child_msg, 5, 0); + ERROR_IF(send, status, == -1); + + close(sv[1]); + exit(0); + } else { + close(sv[1]); + + status = send(sv[0], parent_msg, 5, 0); + ERROR_IF(send, status, == -1); + + status = shutdown(sv[0], SHUT_WR); + ERROR_IF(shutdown, status, == -1); + printf("parent: shutdown(SHUT_WR) performed\n"); + + memset(buf, 0, sizeof(buf)); + ssize_t n = recv(sv[0], buf, sizeof(buf), 0); + ERROR_IF(recv, n, == -1); + + if (n == 0) { + fprintf(stderr, + "FAILURE: Parent received EOF, but expected 'pong'\n"); + exit(EXIT_FAILURE); + } + printf("parent: received '%s' (Shutdown allows reading)\n", buf); + + status = send(sv[0], "garbage", 7, MSG_NOSIGNAL); + if (status != -1 || errno != EPIPE) { + fprintf(stderr, + "WARNING: Expected EPIPE on write after shutdown, got " + "status %d\n", + status); + } else { + printf("parent: verified EPIPE on write after shutdown\n"); + } + + close(sv[0]); + wait(NULL); + } + + return 0; +}