net: lwm2m: Protect send() calls with a mutex
Although LwM2M engine uses cooperative threads, the internal `send()` implementation might trigger context switch when it calls a kernel function, therefore resulting in `send()` call being entered from both the LwM2M thread and the retransmit work. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
e80e655b01
commit
fddeb59911
2 changed files with 23 additions and 1 deletions
|
@ -24,6 +24,7 @@
|
||||||
#define ZEPHYR_INCLUDE_NET_LWM2M_H_
|
#define ZEPHYR_INCLUDE_NET_LWM2M_H_
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
#include <sys/mutex.h>
|
||||||
#include <net/coap.h>
|
#include <net/coap.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,6 +70,7 @@ struct lwm2m_ctx {
|
||||||
struct coap_pending pendings[CONFIG_LWM2M_ENGINE_MAX_PENDING];
|
struct coap_pending pendings[CONFIG_LWM2M_ENGINE_MAX_PENDING];
|
||||||
struct coap_reply replies[CONFIG_LWM2M_ENGINE_MAX_REPLIES];
|
struct coap_reply replies[CONFIG_LWM2M_ENGINE_MAX_REPLIES];
|
||||||
struct k_delayed_work retransmit_work;
|
struct k_delayed_work retransmit_work;
|
||||||
|
struct sys_mutex send_lock;
|
||||||
|
|
||||||
#if defined(CONFIG_LWM2M_DTLS_SUPPORT)
|
#if defined(CONFIG_LWM2M_DTLS_SUPPORT)
|
||||||
/** TLS tag is set by client as a reference used when the
|
/** TLS tag is set by client as a reference used when the
|
||||||
|
|
|
@ -26,6 +26,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
|
#include <sys/mutex.h>
|
||||||
#include <sys/printk.h>
|
#include <sys/printk.h>
|
||||||
#include <net/net_ip.h>
|
#include <net/net_ip.h>
|
||||||
#include <net/http_parser_url.h>
|
#include <net/http_parser_url.h>
|
||||||
|
@ -994,6 +995,8 @@ cleanup:
|
||||||
|
|
||||||
int lwm2m_send_message(struct lwm2m_message *msg)
|
int lwm2m_send_message(struct lwm2m_message *msg)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!msg || !msg->ctx) {
|
if (!msg || !msg->ctx) {
|
||||||
LOG_ERR("LwM2M message is invalid.");
|
LOG_ERR("LwM2M message is invalid.");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1005,11 +1008,16 @@ int lwm2m_send_message(struct lwm2m_message *msg)
|
||||||
|
|
||||||
msg->send_attempts++;
|
msg->send_attempts++;
|
||||||
|
|
||||||
if (send(msg->ctx->sock_fd, msg->cpkt.data, msg->cpkt.offset, 0) < 0) {
|
sys_mutex_lock(&msg->ctx->send_lock, K_FOREVER);
|
||||||
|
rc = send(msg->ctx->sock_fd, msg->cpkt.data, msg->cpkt.offset, 0);
|
||||||
|
sys_mutex_unlock(&msg->ctx->send_lock);
|
||||||
|
if (rc < 0) {
|
||||||
if (msg->type == COAP_TYPE_CON) {
|
if (msg->type == COAP_TYPE_CON) {
|
||||||
coap_pending_clear(msg->pending);
|
coap_pending_clear(msg->pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_ERR("Failed to send packet, err %d", errno);
|
||||||
|
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3769,11 +3777,22 @@ static void retransmit_request(struct k_work *work)
|
||||||
|
|
||||||
LOG_INF("Resending message: %p", msg);
|
LOG_INF("Resending message: %p", msg);
|
||||||
msg->send_attempts++;
|
msg->send_attempts++;
|
||||||
|
|
||||||
|
sys_mutex_lock(&client_ctx->send_lock, K_FOREVER);
|
||||||
|
|
||||||
|
if (msg->ctx == NULL) {
|
||||||
|
LOG_INF("Response for %p already handled", msg);
|
||||||
|
goto next_locked;
|
||||||
|
}
|
||||||
|
|
||||||
if (send(msg->ctx->sock_fd, msg->cpkt.data, msg->cpkt.offset, 0) < 0) {
|
if (send(msg->ctx->sock_fd, msg->cpkt.data, msg->cpkt.offset, 0) < 0) {
|
||||||
LOG_ERR("Error sending lwm2m message: %d", -errno);
|
LOG_ERR("Error sending lwm2m message: %d", -errno);
|
||||||
/* don't error here, retry until timeout */
|
/* don't error here, retry until timeout */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next_locked:
|
||||||
|
sys_mutex_unlock(&client_ctx->send_lock);
|
||||||
|
|
||||||
next:
|
next:
|
||||||
pending = coap_pending_next_to_expire(client_ctx->pendings,
|
pending = coap_pending_next_to_expire(client_ctx->pendings,
|
||||||
CONFIG_LWM2M_ENGINE_MAX_PENDING);
|
CONFIG_LWM2M_ENGINE_MAX_PENDING);
|
||||||
|
@ -4055,6 +4074,7 @@ int lwm2m_engine_context_close(struct lwm2m_ctx *client_ctx)
|
||||||
void lwm2m_engine_context_init(struct lwm2m_ctx *client_ctx)
|
void lwm2m_engine_context_init(struct lwm2m_ctx *client_ctx)
|
||||||
{
|
{
|
||||||
k_delayed_work_init(&client_ctx->retransmit_work, retransmit_request);
|
k_delayed_work_init(&client_ctx->retransmit_work, retransmit_request);
|
||||||
|
sys_mutex_init(&client_ctx->send_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LwM2M Socket Integration */
|
/* LwM2M Socket Integration */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue