mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Implement MSG_COPY option for msgrcv(2).
Implement Queue.Copy and add more tests for it. Updates #135
This commit is contained in:
@@ -386,13 +386,21 @@ func (q *Queue) pop(ctx context.Context, creds *auth.Credentials, mType int64, m
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// Copy copies a message from the queue without deleting it. See
|
||||
// msgrcv(MSG_COPY).
|
||||
func (q *Queue) Copy() (*Message, error) {
|
||||
// Copy copies a message from the queue without deleting it. If no message
|
||||
// exists, an error is returned. See msgrcv(MSG_COPY).
|
||||
func (q *Queue) Copy(mType int64) (*Message, error) {
|
||||
q.mu.Lock()
|
||||
defer q.mu.Unlock()
|
||||
|
||||
return nil, linuxerr.ENOSYS
|
||||
if mType < 0 || q.messages.Empty() {
|
||||
return nil, linuxerr.ENOMSG
|
||||
}
|
||||
|
||||
msg := q.msgAtIndex(mType)
|
||||
if msg == nil {
|
||||
return nil, linuxerr.ENOMSG
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// msgOfType returns the first message with the specified type, nil if no
|
||||
@@ -433,6 +441,17 @@ func (q *Queue) msgOfTypeLessThan(mType int64) (m *Message) {
|
||||
return m
|
||||
}
|
||||
|
||||
// msgAtIndex returns a pointer to a message at given index, nil if non exits.
|
||||
//
|
||||
// Precondition: caller must hold q.mu.
|
||||
func (q *Queue) msgAtIndex(mType int64) *Message {
|
||||
msg := q.messages.Front()
|
||||
for ; mType != 0 && msg != nil; mType-- {
|
||||
msg = msg.Next()
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
// Lock implements ipc.Mechanism.Lock.
|
||||
func (q *Queue) Lock() {
|
||||
q.mu.Lock()
|
||||
|
||||
@@ -123,7 +123,7 @@ var AMD64 = &kernel.SyscallTable{
|
||||
67: syscalls.Supported("shmdt", Shmdt),
|
||||
68: syscalls.Supported("msgget", Msgget),
|
||||
69: syscalls.Supported("msgsnd", Msgsnd),
|
||||
70: syscalls.PartiallySupported("msgrcv", Msgrcv, "Doesn't support MSG_COPY option.", []string{"gvisor.dev/issue/135"}),
|
||||
70: syscalls.Supported("msgrcv", Msgrcv),
|
||||
71: syscalls.PartiallySupported("msgctl", Msgctl, "Only supports IPC_RMID option.", []string{"gvisor.dev/issue/135"}),
|
||||
72: syscalls.PartiallySupported("fcntl", Fcntl, "Not all options are supported.", nil),
|
||||
73: syscalls.PartiallySupported("flock", Flock, "Locks are held within the sandbox only.", nil),
|
||||
@@ -618,7 +618,7 @@ var ARM64 = &kernel.SyscallTable{
|
||||
185: syscalls.ErrorWithEvent("mq_getsetattr", syserror.ENOSYS, "", []string{"gvisor.dev/issue/136"}), // TODO(b/29354921)
|
||||
186: syscalls.Supported("msgget", Msgget),
|
||||
187: syscalls.PartiallySupported("msgctl", Msgctl, "Only supports IPC_RMID option.", []string{"gvisor.dev/issue/135"}),
|
||||
188: syscalls.PartiallySupported("msgrcv", Msgrcv, "Doesn't support MSG_COPY option.", []string{"gvisor.dev/issue/135"}),
|
||||
188: syscalls.Supported("msgrcv", Msgrcv),
|
||||
189: syscalls.Supported("msgsnd", Msgsnd),
|
||||
190: syscalls.Supported("semget", Semget),
|
||||
191: syscalls.Supported("semctl", Semctl),
|
||||
|
||||
@@ -118,7 +118,10 @@ func receive(t *kernel.Task, id ipc.ID, mType int64, maxSize int64, msgCopy, wai
|
||||
}
|
||||
|
||||
if msgCopy {
|
||||
return queue.Copy()
|
||||
if wait || except {
|
||||
return nil, linuxerr.EINVAL
|
||||
}
|
||||
return queue.Copy(mType)
|
||||
}
|
||||
return queue.Receive(t, t, mType, maxSize, wait, truncate, except, pid)
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ bool MsgCopySupported() {
|
||||
errno == ENOSYS);
|
||||
}
|
||||
|
||||
// Test usage of MSG_COPY for msgrcv.
|
||||
// Test msgrcv using MSG_COPY.
|
||||
TEST(MsgqueueTest, MsgCopy) {
|
||||
SKIP_IF(!MsgCopySupported());
|
||||
|
||||
@@ -372,11 +372,6 @@ TEST(MsgqueueTest, MsgCopy) {
|
||||
EXPECT_TRUE(buf == rcv);
|
||||
}
|
||||
|
||||
// Invalid index.
|
||||
msgbuf rcv;
|
||||
EXPECT_THAT(msgrcv(queue.get(), &rcv, 1, 5, MSG_COPY | IPC_NOWAIT),
|
||||
SyscallFailsWithErrno(ENOMSG));
|
||||
|
||||
// Re-receive the messages normally.
|
||||
for (auto& buf : bufs) {
|
||||
msgbuf rcv;
|
||||
@@ -386,6 +381,37 @@ TEST(MsgqueueTest, MsgCopy) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test msgrcv using MSG_COPY with invalid arguments.
|
||||
TEST(MsgqueueTest, MsgCopyInvalidArgs) {
|
||||
SKIP_IF(!MsgCopySupported());
|
||||
|
||||
Queue queue(msgget(IPC_PRIVATE, 0600));
|
||||
ASSERT_THAT(queue.get(), SyscallSucceeds());
|
||||
|
||||
msgbuf rcv;
|
||||
EXPECT_THAT(msgrcv(queue.get(), &rcv, msgSize, 1, MSG_COPY),
|
||||
SyscallFailsWithErrno(EINVAL));
|
||||
|
||||
EXPECT_THAT(
|
||||
msgrcv(queue.get(), &rcv, msgSize, 5, MSG_COPY | MSG_EXCEPT | IPC_NOWAIT),
|
||||
SyscallFailsWithErrno(EINVAL));
|
||||
}
|
||||
|
||||
// Test msgrcv using MSG_COPY with invalid indices.
|
||||
TEST(MsgqueueTest, MsgCopyInvalidIndex) {
|
||||
SKIP_IF(!MsgCopySupported());
|
||||
|
||||
Queue queue(msgget(IPC_PRIVATE, 0600));
|
||||
ASSERT_THAT(queue.get(), SyscallSucceeds());
|
||||
|
||||
msgbuf rcv;
|
||||
EXPECT_THAT(msgrcv(queue.get(), &rcv, msgSize, -3, MSG_COPY | IPC_NOWAIT),
|
||||
SyscallFailsWithErrno(ENOMSG));
|
||||
|
||||
EXPECT_THAT(msgrcv(queue.get(), &rcv, msgSize, 5, MSG_COPY | IPC_NOWAIT),
|
||||
SyscallFailsWithErrno(ENOMSG));
|
||||
}
|
||||
|
||||
// Test msgrcv (most probably) blocking on an empty queue.
|
||||
TEST(MsgqueueTest, MsgRcvBlocking) {
|
||||
Queue queue(msgget(IPC_PRIVATE, 0600));
|
||||
|
||||
Reference in New Issue
Block a user