eclipse / paho.mqtt.embedded-c

Paho MQTT C client library for embedded systems. Paho is an Eclipse IoT project (https://iot.eclipse.org/)

Home Page:https://eclipse.org/paho

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Suspected bug with MQTTYield() / cycle()

diewelt opened this issue · comments

I experienced a weird issue with MQTTClient-C. Without an explicit error MQTTYield() returns error on both, IoT board and host subscriber/publisher. I used Paho MQTT library for my board and host application.

Socket has to be closed if an error is returned while reading or writing in my thought, because it is already closed or something wrong with the socket. And it's clearer when we check cycle() returns MQTTCLNT_FAILURE(== -1) on all failures.

Here is the scenario where MQTTYield() returns an error without an explicit error.

MQTTYield() is given 1 sec and readPacket() spends 990 ms. And then context switching occurs. The other task consumes the remaing 10 ms for the timer. Now sendPacket() is called. Timer is already expired at the point when sendPacket() is called. So sendPacket() returns an MQTTCLNT_FAILURE, cycle() returns MQTTCLNT_FAILURE, and then MQTTYield() returns MQTTCLNT_FAILURE.

`int cycle(MQTTClient* c, Timer* timer)
{
int packet_type = readPacket(c, timer);

switch (packet_type)
{

---- snip ---

context switching (for example)
timer expired here

---- snip ---
case PUBLISH:
rc = sendPacket(c, len, timer);
if(rc == MQTTCLNT_FAILURE)
goto exit; // there was a problem
break;
---- snip ---
}

return rc;

}`

In this scenario, the application has to close the socket() without an actual error. In my setup this happens too often(several tens of times a day).

The simplest solution is to give a reasonable time to sendPacket() irregardless of the remaining time after readPacket(). It's safe enough because sendPacket() is executed within certain bounded time in most systems.

`
int cycle(MQTTClient* c, Timer* timer)
{
Timer resonableConstantTimer;
int packet_type = readPacket(c, timer);

TimerInit(&resonableConstantTimer);
TimerCountdownMS(&resonableConstantTimer, RESONABLE_CONSTANT_TIME);

switch (packet_type)
{

---- snip ---
case PUBLISH:
rc = sendPacket(c, len, resonableConstantTimer);
if(rc == MQTTCLNT_FAILURE)
goto exit; // there was a problem
break;
---- snip ---
}

return rc;

}
`

Kyle Shim