buglwIP - A Lightweight TCP/IP stack - Bugs: bug #59049, MQTT in FreeRTOS tasks give error...

 
 

You are not allowed to post comments on this tracker with your current authentication level.

bug #59049: MQTT in FreeRTOS tasks give error on TCP-write/output

Submitted by:  Andre <klaasvortex>
Submitted on:  Tue 01 Sep 2020 11:48:49 AM UTC  
 
Category:  Contrib Severity:  3 - Normal
Item Group:  Faulty Behaviour Status:  None
Privacy:  Public Assigned to:  None
Open/Closed:  Open Planned Release:  None
lwIP version:  2.1.1

Thu 01 Oct 2020 09:49:23 AM UTC, comment #4: 

Hi Dejan,

First I am not an expert, so keep that in mind.

I think the problem can be simular to mine, since crossing thread on LWIP can/will mangle up the tcp/ip stack. It can take a while but it will.

First the TCP/IP is a REAL Freertos thread, lets call this task0, but DHCP is running on the LWIP timers (which run in task0). This is also true for HTTPD. So what I did is running the MQTT thread in a lwip timer, so MQTT runs from task0. This solved my troubles.

There are CYCLIC timers in LWIP, but they are not accesibly to 'user-program'. But you can add them into the source code.
I do prefer my one-shot timer, since it will not touch the LWIP code.

---------------------------

So for example. Something like this.

main()
{
  // This will start the MQTT System after 15 seconds
 sys_timeout(15000, MQTT_Task, NULL);
}

// So this is the task that does the workload and it will restart every period
void MQTT_Task(void *arg)
{
    err_t err;

    (void) arg;

   // RESTART THE TASK
    tMS reloadTimer = 1000;

    if (dns_gethostbyname( dMQTT_SERVER_NAME, &mqttTask.serverIP, MQTTServerFound, NULL) == ERR_OK)
    {
        switch (mqttTask.status)
        {
            case eMQTT_INIT:
                mqttTask.counterMS = dMS(0);
                mqtt_disconnect(mqttTask.client);
                err = mqtt_client_connect(mqttTask.client, &mqttTask.serverIP, dMQTT_PORT, MQTT_ConnectionCB, 0, &ci);
                if(err == ERR_ISCONN)
}

Andre <klaasvortex>
Wed 30 Sep 2020 05:58:18 PM UTC, comment #3: 

Hi David, Andre,

I am having the same issue here. I am using Lwip + FreeRtos + Mqtt on STM32F746 MCU. I have noticed strange behavior when packets to be sent by Mqtt are bigger than one TCP packet (something like > 1450 bytes). Then in mqtt_output_send() I have altcp_sndbuf(tcpb) returning ZERO. and nothing gets send, and furthermore, my ringbuf gets filled-up by next consequential atempts and eventualy I end up  with MEM ERROR (but this is product of the first corruption of course.

However to make things even worse, this only happens sometimes, and only happens on public networks. On local network connection (to localhost MQTT Broker) things work just fine for days and days.

As soon as I connect to public network on a dedicated broker (broker listening just my device - NOT a PUBLIC BROKER but proprietary located on DigitalOcean servers) the system works until the first MCU soft reset... when the library simply would not send packets bigger than 1450 bytes anymore, or in other words segmenting the big packet paylod to several will not even start cause mqtt_output_send has issues and I cannot seem to catch what exacly happens, its hard to debug even why altcp_sndbuf(tcpb) is returning ZERO??...

Obviously it not thread safe to call mqtt functions from third-party thread in freertos, but I dont know what minimum effort I need to make to restructure the code ... which thread I need to call my mqtt functions from?

I have this list of threads running in freertos:
IDLE
TCP/IP
DHCP
EthIf
HTTP
myMQTT

The last two are my tasks, and I call mqtt lib functions from myMQTT.
I would happily restructure it and place it to any other thread but I would appreciete any help on this on the minimal approach.

I am not at all an expert in lwip, so its even harder to trace things around for me.

Please help

Dejan <dejandigitex>
Fri 18 Sep 2020 01:35:39 PM UTC, comment #2: 

Hi David,

Ok, thank you very much. I will reformat the code into doing just that.

Andre <klaasvortex>
Fri 18 Sep 2020 09:58:18 AM UTC, comment #1: 

Hi Andre,

You must call mqtt API from the LWIP thread context as it use the raw ALTCP api.

To do that, you can use the tcpip_callback() or tcpip_callback_wait() functions for example.

Regards,
David

David GIRAULT <dgirault>
Tue 01 Sep 2020 11:48:49 AM UTC, original submission:  

When using MQTT to sent data from seperate threads (FreeRTOS) I got errors on LWIP. (and sometimes deadlocks in loops)

==
I am using MQTT to sent logging from multiple tasks to a MQTT server. My own Logging writing function is protected by mutex and is thread safe.

However the LWIP-thread is NOT the same as my Logging thread. This gives (occasionly) errors on LWIP-tcp-write and output functions.

Looking into mqtt.c, the public publish sub/un sub function do both call

  mqtt_output_send(&client->output, client->conn);

Which use tcp->write/output. This will cause the fault. Since these functions are not protected (thread safe)and should only be called from the LWIP thread. (I think)

Remember the publish/sub.unsub functions copy the data into a ringbuffer. Then the sent function will transmit the ringbuffer data. So we can use this buffer to do the next thing.

By removing the mqtt_output_send from these 2 public mqtt-functions, the errors are gone and everything works. Since the tcp->poll function will take over the transmission and is called from the LWIP-task. The poll function will transmit any data from the ringbuffer.

But there will be a delay before sending since it is started when the poll runs and not directly sent after call pusblish.

Subscribtions are no problem since they are called from the LWIP thread.

With this solution I can call mqtt_publish from every task. Which I would like to do.

But I am not sure if this is the correct way to do so.

Is there a better way to do this ?

Andre <klaasvortex>

 

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by dejandigitex (Posted a comment)
  • -email is unavailable- added by dgirault (Posted a comment)
  • -email is unavailable- added by klaasvortex (Submitted the item)
  •  

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.

     

     

     

    No changes have been made to this item

    Back to the top


    Powered by Savane 3.7