localsocket: fix cmsg

This commit is contained in:
Matheus
2025-02-08 20:22:18 -03:00
parent d119d7123b
commit 73929bfd57
6 changed files with 25 additions and 17 deletions
+2 -2
View File
@@ -196,7 +196,7 @@ int fd_clone(proc_t *targproc) {
return error; return error;
} }
int fd_insert(file_t *file, int *fdp) { int fd_insert(file_t *file, int *fdp, int flags) {
proc_t *proc = current_thread()->proc; proc_t *proc = current_thread()->proc;
int err = 0; int err = 0;
MUTEX_ACQUIRE(&proc->fdmutex); MUTEX_ACQUIRE(&proc->fdmutex);
@@ -210,7 +210,7 @@ int fd_insert(file_t *file, int *fdp) {
} }
proc->fd[fd].file = file; proc->fd[fd].file = file;
proc->fd[fd].flags = 0; proc->fd[fd].flags = flags;
FILE_HOLD(file); FILE_HOLD(file);
*fdp = fd; *fdp = fd;
+1
View File
@@ -89,6 +89,7 @@ typedef struct {
#define SOCK_DGRAM 2 #define SOCK_DGRAM 2
#define SOCK_RAW 3 #define SOCK_RAW 3
#define MSG_CMSG_CLOEXEC 0x40000000
#define MSG_CTRUNC 0x8 #define MSG_CTRUNC 0x8
#define MSG_PEEK 2 #define MSG_PEEK 2
#define MSG_WAITALL 0x100 #define MSG_WAITALL 0x100
+1 -1
View File
@@ -28,7 +28,7 @@ int fd_dup(int oldfd, int newfd, bool exact, int flags, int *ret);
int fd_clone(proc_t *proc); int fd_clone(proc_t *proc);
int fd_setflags(int fd, int flags); int fd_setflags(int fd, int flags);
int fd_getflags(int fd, int *flags); int fd_getflags(int fd, int *flags);
int fd_insert(file_t *file, int *fdp); int fd_insert(file_t *file, int *fdp, int flags);
#define FILE_LOCK(x) MUTEX_ACQUIRE(&(x)->mutex) #define FILE_LOCK(x) MUTEX_ACQUIRE(&(x)->mutex)
#define FILE_UNLOCK(x) MUTEX_RELEASE(&(x)->mutex) #define FILE_UNLOCK(x) MUTEX_RELEASE(&(x)->mutex)
+1
View File
@@ -51,6 +51,7 @@ typedef struct {
#define SOCKET_RECV_FLAGS_PEEK 0x8000000000000000l #define SOCKET_RECV_FLAGS_PEEK 0x8000000000000000l
#define SOCKET_RECV_FLAGS_WAITALL 0x4000000000000000l #define SOCKET_RECV_FLAGS_WAITALL 0x4000000000000000l
#define SOCKET_RECV_FLAGS_CTRLTRUNCATED 0x2000000000000000l #define SOCKET_RECV_FLAGS_CTRLTRUNCATED 0x2000000000000000l
#define SOCKET_RECV_FLAGS_CLOEXEC_CTRL 0x1000000000000000l
#define SOCKET_SEND_FLAGS_NOSIGNAL 0x8000000000000000l #define SOCKET_SEND_FLAGS_NOSIGNAL 0x8000000000000000l
typedef struct socketops_t { typedef struct socketops_t {
+16 -13
View File
@@ -71,11 +71,14 @@ static int datapoll(localsocket_t *local, localsocket_t *peer, int events) {
int revents = 0; int revents = 0;
// data to read? // data to read?
if ((events & POLLIN) && RINGBUFFER_DATACOUNT(&local->ringbuffer)) if ((events & POLLIN) && (RINGBUFFER_DATACOUNT(&local->ringbuffer) || (peer->socket.shutdown & SOCKET_SHUTDOWN_WRITE)))
revents |= POLLIN; revents |= POLLIN;
// XXX is this the correct behaviour?
if ((events & POLLOUT) && (peer->socket.shutdown & SOCKET_SHUTDOWN_READ))
revents |= POLLHUP;
// space to write? // space to write?
if ((events & POLLOUT) && RINGBUFFER_DATACOUNT(&peer->ringbuffer) != SOCKET_BUFFER) else if ((events & POLLOUT) && RINGBUFFER_DATACOUNT(&peer->ringbuffer) != SOCKET_BUFFER)
revents |= POLLOUT; revents |= POLLOUT;
return revents; return revents;
@@ -177,7 +180,7 @@ static int sendctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, size_t datas
if (ctrl == NULL) { if (ctrl == NULL) {
// if there is no control data, there is no need to add a barrier // if there is no control data, there is no need to add a barrier
// increase the bytes in the current section // increase the bytes in the current section
peer->bytesremaining[peer->barrierwrite] += datasent; peer->bytesremaining[peer->barrierwrite % BARRIER_SIZE] += datasent;
return 0; return 0;
} }
@@ -233,9 +236,10 @@ static int sendctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, size_t datas
// create a new barrier secion // create a new barrier secion
__assert(peer->barrierwrite != peer->barriercurrent + BARRIER_SIZE); __assert(peer->barrierwrite != peer->barriercurrent + BARRIER_SIZE);
peer->barrierwrite++;
peer->filesremaining[peer->barrierwrite % BARRIER_SIZE] = fdcount; peer->filesremaining[peer->barrierwrite % BARRIER_SIZE] = fdcount;
peer->bytesremaining[peer->barrierwrite % BARRIER_SIZE] = datasent; peer->bytesremaining[peer->barrierwrite % BARRIER_SIZE] = datasent;
++peer->barrierwrite;
} }
ctrl = SOCK_CTRL_NEXT(ctrl); ctrl = SOCK_CTRL_NEXT(ctrl);
@@ -244,7 +248,7 @@ static int sendctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, size_t datas
return error; return error;
} }
static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *truncated, size_t *receivedlen) { static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *truncated, size_t *receivedlen, uintmax_t flags) {
localsocket_t *localsocket = (localsocket_t *)socket; localsocket_t *localsocket = (localsocket_t *)socket;
int error = 0; int error = 0;
*receivedlen = 0; *receivedlen = 0;
@@ -258,7 +262,7 @@ static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *trunca
// - number fds that fit in the data of the control // - number fds that fit in the data of the control
// - files in the current section // - files in the current section
// - files actually in the ringbuffer // - files actually in the ringbuffer
size_t actualcount = min(min((len - sizeof(sockctrl_t)) / sizeof(int), filecount), localsocket->filesremaining[localsocket->barriercurrent]); size_t actualcount = min(min((len - sizeof(sockctrl_t)) / sizeof(int), filecount), localsocket->filesremaining[localsocket->barriercurrent % BARRIER_SIZE]);
if (actualcount == 0) if (actualcount == 0)
goto discard; goto discard;
@@ -269,8 +273,7 @@ static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *trunca
// read the file pointers and insert them into the process fd table // read the file pointers and insert them into the process fd table
file_t *file; file_t *file;
__assert(ringbuffer_read(&localsocket->fds, &file, sizeof(file_t *)) == sizeof(file_t *)); __assert(ringbuffer_read(&localsocket->fds, &file, sizeof(file_t *)) == sizeof(file_t *));
if (fd_insert(file, &fds[donecount], (flags & SOCKET_RECV_FLAGS_CLOEXEC_CTRL) ? O_CLOEXEC : 0)) {
if (fd_insert(file, &fds[donecount])) {
fd_release(file); fd_release(file);
break; break;
} }
@@ -286,7 +289,7 @@ static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *trunca
memcpy(ctrl->data, fds, donecount * sizeof(int)); memcpy(ctrl->data, fds, donecount * sizeof(int));
// prepare for discarding the rest later // prepare for discarding the rest later
localsocket->filesremaining[localsocket->barriercurrent] -= donecount; localsocket->filesremaining[localsocket->barriercurrent % BARRIER_SIZE] -= donecount;
*receivedlen += ctrl->length; *receivedlen += ctrl->length;
} }
@@ -294,14 +297,14 @@ static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *trunca
discard: discard:
// discard the rest // discard the rest
file_t *file = NULL; file_t *file = NULL;
for (int i = 0; i < localsocket->filesremaining[localsocket->barriercurrent]; ++i) { for (int i = 0; i < localsocket->filesremaining[localsocket->barriercurrent % BARRIER_SIZE]; ++i) {
ringbuffer_read(&localsocket->fds, &file, sizeof(file_t *)); ringbuffer_read(&localsocket->fds, &file, sizeof(file_t *));
fd_release(file); fd_release(file);
} }
*truncated = file != NULL; *truncated = file != NULL;
localsocket->filesremaining[localsocket->barriercurrent] = 0; localsocket->filesremaining[localsocket->barriercurrent % BARRIER_SIZE] = 0;
return error; return error;
} }
@@ -447,7 +450,7 @@ static int localsock_recv(socket_t *socket, sockdesc_t *sockdesc) {
// receive control data // receive control data
bool truncated; bool truncated;
error = recvctrl(socket, sockdesc->ctrl, sockdesc->ctrllen, &truncated, &sockdesc->ctrldone); error = recvctrl(socket, sockdesc->ctrl, sockdesc->ctrllen, &truncated, &sockdesc->ctrldone, flags);
if (error) if (error)
goto leave; goto leave;
@@ -458,7 +461,7 @@ static int localsock_recv(socket_t *socket, sockdesc_t *sockdesc) {
// check for a barrier from control data // check for a barrier from control data
if (localsocket->bytesremaining[localsocket->barriercurrent % BARRIER_SIZE]) { if (localsocket->bytesremaining[localsocket->barriercurrent % BARRIER_SIZE]) {
recvcount = min(recvcount, localsocket->bytesremaining[localsocket->barriercurrent]); recvcount = min(recvcount, localsocket->bytesremaining[localsocket->barriercurrent % BARRIER_SIZE]);
// check if we should step forward from that barrier // check if we should step forward from that barrier
localsocket->bytesremaining[localsocket->barriercurrent % BARRIER_SIZE] -= recvcount; localsocket->bytesremaining[localsocket->barriercurrent % BARRIER_SIZE] -= recvcount;
+4 -1
View File
@@ -6,7 +6,7 @@
#include <kernel/file.h> #include <kernel/file.h>
#include <kernel/alloc.h> #include <kernel/alloc.h>
#define KNOWN_FLAGS (MSG_PEEK | MSG_WAITALL) #define KNOWN_FLAGS (MSG_PEEK | MSG_WAITALL | MSG_CMSG_CLOEXEC)
syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) { syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) {
__assert((flags & ~KNOWN_FLAGS) == 0); __assert((flags & ~KNOWN_FLAGS) == 0);
@@ -55,6 +55,9 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
if (flags & MSG_WAITALL) if (flags & MSG_WAITALL)
recvflags |= SOCKET_RECV_FLAGS_WAITALL; recvflags |= SOCKET_RECV_FLAGS_WAITALL;
if (flags & MSG_CMSG_CLOEXEC)
recvflags |= SOCKET_RECV_FLAGS_CLOEXEC_CTRL;
iovec_iterator_t iovec_iterator; iovec_iterator_t iovec_iterator;
sockdesc_t desc = { sockdesc_t desc = {
.addr = &sockaddr, .addr = &sockaddr,