-
Notifications
You must be signed in to change notification settings - Fork 5.4k
[libc/posix] Fix mq_send() to block when queue is full per POSIX standard #11197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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) | ||||||||||||||||||||||||||||||||||
|
|
@@ -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; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
@@ -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; | ||||||||||||||||||||||||||||||||||
| struct mqueue_file *mq_file; | ||||||||||||||||||||||||||||||||||
| mq_file = fd_get(id)->vnode->data; | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
| 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
AI
Feb 18, 2026
There was a problem hiding this comment.
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);| rt_set_errno(EMSGSIZE); | |
| rt_set_errno(EMSGSIZE); | |
| else if (result == -RT_EINVAL) | |
| rt_set_errno(EINVAL); |
There was a problem hiding this comment.
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
tickis initialized to0on line 352, but this initialization is unnecessary sincetickis always assigned a value before use (either fromrt_timespec_to_tick()on line 364 orRT_WAITING_FOREVERon line 366). This follows the same pattern asmq_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.