From 86cff0db4babe9a302237e0f0714f2d7f9b96024 Mon Sep 17 00:00:00 2001 From: wdfk-prog <1425075683@qq.com> Date: Wed, 5 Nov 2025 15:55:14 +0800 Subject: [PATCH] fix(can): Resolve potential race condition in message transmission Setting the send status flag `sndchange` after calling the can->ops->sendmsg function could lead to a race condition if a transmission timeout occurs, resulting in incorrect state handling. This patch moves the operation of setting the `sndchange` flag to before the call to can->ops->sendmsg. This ensures that the mailbox's status is correctly marked as "sending" before the hardware begins transmission, making the driver's state management more robust and reliable, especially in handling exceptions like timeouts. Additionally, new macros for CAN filter modes have been added in dev_can.h. --- components/drivers/can/dev_can.c | 5 +++-- components/drivers/include/drivers/dev_can.h | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/components/drivers/can/dev_can.c b/components/drivers/can/dev_can.c index 73aee2f0943..e0cf0db9b27 100644 --- a/components/drivers/can/dev_can.c +++ b/components/drivers/can/dev_can.c @@ -186,6 +186,7 @@ rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *da no = ((rt_ubase_t)tx_tosnd - (rt_ubase_t)tx_fifo->buffer) / sizeof(struct rt_can_sndbxinx_list); tx_tosnd->result = RT_CAN_SND_RESULT_WAIT; rt_completion_init(&tx_tosnd->completion); + can->status.sndchange |= 1<ops->sendmsg(can, data, no) != RT_EOK) { /* send failed. */ @@ -196,7 +197,6 @@ rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *da goto err_ret; } - can->status.sndchange |= 1<completion), RT_CANSND_MSG_TIMEOUT) != RT_EOK) { level = rt_hw_local_irq_disable(); @@ -286,11 +286,12 @@ rt_inline int _can_int_tx_priv(struct rt_can_device *can, const struct rt_can_ms tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_WAIT; rt_hw_local_irq_enable(level); + can->status.sndchange |= 1<ops->sendmsg(can, data, no) != RT_EOK) { continue; } - can->status.sndchange |= 1<buffer[no].completion), RT_CANSND_MSG_TIMEOUT) != RT_EOK) { can->status.sndchange &= ~ (1<