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;
}
int fd_insert(file_t *file, int *fdp) {
int fd_insert(file_t *file, int *fdp, int flags) {
proc_t *proc = current_thread()->proc;
int err = 0;
MUTEX_ACQUIRE(&proc->fdmutex);
@@ -210,7 +210,7 @@ int fd_insert(file_t *file, int *fdp) {
}
proc->fd[fd].file = file;
proc->fd[fd].flags = 0;
proc->fd[fd].flags = flags;
FILE_HOLD(file);
*fdp = fd;
+1
View File
@@ -89,6 +89,7 @@ typedef struct {
#define SOCK_DGRAM 2
#define SOCK_RAW 3
#define MSG_CMSG_CLOEXEC 0x40000000
#define MSG_CTRUNC 0x8
#define MSG_PEEK 2
#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_setflags(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_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_WAITALL 0x4000000000000000l
#define SOCKET_RECV_FLAGS_CTRLTRUNCATED 0x2000000000000000l
#define SOCKET_RECV_FLAGS_CLOEXEC_CTRL 0x1000000000000000l
#define SOCKET_SEND_FLAGS_NOSIGNAL 0x8000000000000000l
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;
// 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;
// XXX is this the correct behaviour?
if ((events & POLLOUT) && (peer->socket.shutdown & SOCKET_SHUTDOWN_READ))
revents |= POLLHUP;
// space to write?
if ((events & POLLOUT) && RINGBUFFER_DATACOUNT(&peer->ringbuffer) != SOCKET_BUFFER)
else if ((events & POLLOUT) && RINGBUFFER_DATACOUNT(&peer->ringbuffer) != SOCKET_BUFFER)
revents |= POLLOUT;
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 there is no control data, there is no need to add a barrier
// increase the bytes in the current section
peer->bytesremaining[peer->barrierwrite] += datasent;
peer->bytesremaining[peer->barrierwrite % BARRIER_SIZE] += datasent;
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
__assert(peer->barrierwrite != peer->barriercurrent + BARRIER_SIZE);
peer->barrierwrite++;
peer->filesremaining[peer->barrierwrite % BARRIER_SIZE] = fdcount;
peer->bytesremaining[peer->barrierwrite % BARRIER_SIZE] = datasent;
++peer->barrierwrite;
}
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;
}
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;
int error = 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
// - files in the current section
// - 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)
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
file_t *file;
__assert(ringbuffer_read(&localsocket->fds, &file, sizeof(file_t *)) == sizeof(file_t *));
if (fd_insert(file, &fds[donecount])) {
if (fd_insert(file, &fds[donecount], (flags & SOCKET_RECV_FLAGS_CLOEXEC_CTRL) ? O_CLOEXEC : 0)) {
fd_release(file);
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));
// prepare for discarding the rest later
localsocket->filesremaining[localsocket->barriercurrent] -= donecount;
localsocket->filesremaining[localsocket->barriercurrent % BARRIER_SIZE] -= donecount;
*receivedlen += ctrl->length;
}
@@ -294,14 +297,14 @@ static int recvctrl(socket_t *socket, sockctrl_t *ctrl, size_t len, bool *trunca
discard:
// discard the rest
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 *));
fd_release(file);
}
*truncated = file != NULL;
localsocket->filesremaining[localsocket->barriercurrent] = 0;
localsocket->filesremaining[localsocket->barriercurrent % BARRIER_SIZE] = 0;
return error;
}
@@ -447,7 +450,7 @@ static int localsock_recv(socket_t *socket, sockdesc_t *sockdesc) {
// receive control data
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)
goto leave;
@@ -458,7 +461,7 @@ static int localsock_recv(socket_t *socket, sockdesc_t *sockdesc) {
// check for a barrier from control data
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
localsocket->bytesremaining[localsocket->barriercurrent % BARRIER_SIZE] -= recvcount;
+4 -1
View File
@@ -6,7 +6,7 @@
#include <kernel/file.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) {
__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)
recvflags |= SOCKET_RECV_FLAGS_WAITALL;
if (flags & MSG_CMSG_CLOEXEC)
recvflags |= SOCKET_RECV_FLAGS_CLOEXEC_CTRL;
iovec_iterator_t iovec_iterator;
sockdesc_t desc = {
.addr = &sockaddr,