Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 50 additions & 15 deletions components/libc/posix/ipc/mqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,10 @@ RTM_EXPORT(mq_receive);
* The priority of the message is specified by the msg_prio parameter.
* If either the message queue identified by id or the msg_ptr buffer is a null pointer, errno is set to EINVAL,
* indicating an invalid argument, and the function returns -1.
* The function then attempts to send the message to the message queue using the rt_mq_send_wait_prio() function
* with zero timeout and uninterruptible mode.
* If the message queue is full, the function blocks until space becomes available,
* following POSIX standard behavior.
* If the message is successfully sent, the function returns 0.
* If an error occurs during the send operation, errno is set to EBADF, indicating a bad file descriptor,
* If an error occurs during the send operation, errno is set appropriately,
* and the function returns -1.
*/
int mq_send(mqd_t id, const char *msg_ptr, size_t msg_len, unsigned msg_prio)
Expand All @@ -245,11 +245,18 @@ int mq_send(mqd_t id, const char *msg_ptr, size_t msg_len, unsigned msg_prio)
rt_set_errno(EINVAL);
return -1;
}
result = rt_mq_send_wait_prio(mq, (void *)msg_ptr, msg_len, msg_prio, 0, RT_UNINTERRUPTIBLE);
result = rt_mq_send_wait_prio(mq, (void *)msg_ptr, msg_len, msg_prio, RT_WAITING_FOREVER, RT_UNINTERRUPTIBLE);
if (result == RT_EOK)
return 0;

rt_set_errno(EBADF);
if (result == -RT_EINTR)
rt_set_errno(EINTR);
else if (result == -RT_ERROR)
rt_set_errno(EMSGSIZE);
else if (result == -RT_EINVAL)
rt_set_errno(EINVAL);
else
rt_set_errno(EBADF);

return -1;
}
Expand Down Expand Up @@ -320,30 +327,58 @@ ssize_t mq_timedreceive(mqd_t id,
RTM_EXPORT(mq_timedreceive);

/**
* @brief Sends a message to a message queue with a timeout (not supported).
* @brief Sends a message to a message queue with a timeout.
* @param id Message queue descriptor.
* @param msg_ptr Pointer to the buffer containing the message to be sent.
* @param msg_len Size of the message to be sent.
* @param msg_prio Priority of the message to be sent.
* @param abs_timeout Pointer to a struct timespec specifying the absolute timeout value (ignored).
* @param abs_timeout Pointer to a struct timespec specifying the absolute timeout value (ignored if null).
* @return Upon successful completion, returns 0;
* otherwise, returns -1 and sets errno to indicate the error.
*
* @note This function attempts to send a message to the message queue identified by id with a specified timeout,
* but timed send is not supported in the RT-Thread environment.
* Therefore, the function simply delegates the message sending operation to the mq_send() function,
* which does not involve a timeout.
* The abs_timeout parameter is ignored, and the message is sent without waiting for a timeout to occur.
* The function returns the result of the mq_send() function, which indicates whether the message was successfully sent.
* @note This function sends a message to the message queue identified by id with a specified timeout.
* If the message queue is full and the timeout has not expired, the function blocks.
* If abs_timeout is NULL, the function waits indefinitely (same as mq_send).
* If the timeout expires before space becomes available, errno is set to ETIMEDOUT.
*/
int mq_timedsend(mqd_t id,
const char *msg_ptr,
size_t msg_len,
unsigned msg_prio,
const struct timespec *abs_timeout)
{
/* RT-Thread does not support timed send */
return mq_send(id, msg_ptr, msg_len, msg_prio);
rt_mq_t mq;
rt_err_t result;
int tick = 0;
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code style: Variable initialization / 代码风格:变量初始化

English: The variable tick is initialized to 0 on line 352, but this initialization is unnecessary since tick is always assigned a value before use (either from rt_timespec_to_tick() on line 364 or RT_WAITING_FOREVER on line 366). This follows the same pattern as mq_timedreceive() on line 298.

中文:变量 tick 在第 352 行初始化为 0,但这个初始化是不必要的,因为 tick 在使用前总是会被赋值(要么是第 364 行的 rt_timespec_to_tick(),要么是第 366 行的 RT_WAITING_FOREVER)。这与 mq_timedreceive() 第 298 行的模式相同。

Note: This is a minor style issue and the code is functionally correct. The initialization to 0 does not cause any problems.

Suggested change
int tick = 0;
int tick;

Copilot uses AI. Check for mistakes.
struct mqueue_file *mq_file;
mq_file = fd_get(id)->vnode->data;
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing null pointer check for fd_get() return value / 缺少 fd_get() 返回值的空指针检查

English: The code directly dereferences fd_get(id)->vnode->data without checking if fd_get() returns NULL. If fd_get() returns NULL (e.g., invalid file descriptor), this will cause a segmentation fault. Other code in the codebase (e.g., components/libc/posix/io/poll/poll.c:216-219) shows that fd_get() can return NULL and should be checked before dereferencing.

中文:代码直接解引用 fd_get(id)->vnode->data 而没有检查 fd_get() 是否返回 NULL。如果 fd_get() 返回 NULL(例如无效的文件描述符),这将导致段错误。代码库中的其他代码(例如 components/libc/posix/io/poll/poll.c:216-219)显示 fd_get() 可能返回 NULL,应在解引用前进行检查。

Suggested fix: Add null pointer check after line 354:

struct dfs_file *df = fd_get(id);
if (!df || !df->vnode) {
    rt_set_errno(EBADF);
    return -1;
}
mq_file = df->vnode->data;
Suggested change
mq_file = fd_get(id)->vnode->data;
struct dfs_file *df;
df = fd_get(id);
if (!df || !df->vnode)
{
rt_set_errno(EBADF);
return -1;
}
mq_file = (struct mqueue_file *)df->vnode->data;
if (!mq_file)
{
rt_set_errno(EBADF);
return -1;
}

Copilot uses AI. Check for mistakes.
mq = (rt_mq_t)mq_file->data;

if ((mq == RT_NULL) || (msg_ptr == RT_NULL))
{
rt_set_errno(EINVAL);
return -1;
}

if (abs_timeout != RT_NULL)
tick = rt_timespec_to_tick(abs_timeout);
else
tick = RT_WAITING_FOREVER;

result = rt_mq_send_wait_prio(mq, (void *)msg_ptr, msg_len, msg_prio, tick, RT_UNINTERRUPTIBLE);
if (result == RT_EOK)
return 0;

if (result == -RT_ETIMEOUT)
rt_set_errno(ETIMEDOUT);
else if (result == -RT_EINTR)
rt_set_errno(EINTR);
else if (result == -RT_ERROR)
rt_set_errno(EMSGSIZE);
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent error handling for -RT_EINVAL / -RT_EINVAL 错误处理不一致

English: The error handling in mq_timedsend() (line 378) does not include a case for -RT_EINVAL, while mq_send() includes it (line 256-257). According to src/ipc.c, _rt_mq_send_wait() returns -RT_EINVAL when invalid parameters are passed through RT_ASSERT checks. This inconsistency means -RT_EINVAL in mq_timedsend() will be mapped to EBADF instead of EINVAL, which is incorrect.

中文:mq_timedsend() 中的错误处理(第 378 行)不包含 -RT_EINVAL 的情况,而 mq_send() 包含它(第 256-257 行)。根据 src/ipc.c,当通过 RT_ASSERT 检查传递无效参数时,_rt_mq_send_wait() 返回 -RT_EINVAL。这种不一致意味着 mq_timedsend() 中的 -RT_EINVAL 将被映射到 EBADF 而不是 EINVAL,这是不正确的。

Suggested fix: Add the same case in mq_timedsend() error handling (after line 377):

else if (result == -RT_EINVAL)
    rt_set_errno(EINVAL);
Suggested change
rt_set_errno(EMSGSIZE);
rt_set_errno(EMSGSIZE);
else if (result == -RT_EINVAL)
rt_set_errno(EINVAL);

Copilot uses AI. Check for mistakes.
else
rt_set_errno(EBADF);

return -1;
}
RTM_EXPORT(mq_timedsend);

Expand Down
Loading