CORRUPT HEAP in multithread webserver with netconn API

JKozlo
Posts: 3
Joined: Fri Sep 15, 2017 2:23 pm

CORRUPT HEAP in multithread webserver with netconn API

Postby JKozlo » Sun Oct 01, 2017 2:23 pm

Hi,
In my app I have simple webserver, which get measure from few ESP8266 and then send it to thingspeak. Everything works fine when I don't use task and after accept I call function which handle with request, but when I use task and after accept I create task which handle with request, I get Corrupt heap error.

Code: Select all

CORRUPT HEAP: multi_heap.c:395 detected at 0x3ffbf968
abort() was called at PC 0x40086955 on core 1
0x40086955: multi_heap_assert at C:/esp/msys32/esp/esp-idf/components/heap/multi_heap.c:615 (discriminator 1)
 (inlined by) multi_heap_free_impl at C:/esp/msys32/esp/esp-idf/components/heap/multi_heap.c:395 (discriminator 1)


Backtrace: 0x40086f10:0x3ffc2f90 0x4008700f:0x3ffc2fb0 0x40086955:0x3ffc2fd0 0x4008285e:0x3ffc2ff0 0x40082c95:0x3ffc3010 0x4000bec7:
0x3ffc3030 0x400f43b9:0x3ffc3050 0x400f447b:0x3ffc3070 0x4011cae6:0x3ffc3090 0x4011d8cf:0x3ffc30c0 0x400fae31:0x3ffc30e0
0x40086f10: invoke_abort at C:/esp/msys32/esp/esp-idf/components/esp32/panic.c:553

0x4008700f: abort at C:/esp/msys32/esp/esp-idf/components/esp32/panic.c:553

0x40086955: multi_heap_assert at C:/esp/msys32/esp/esp-idf/components/heap/multi_heap.c:615 (discriminator 1)
 (inlined by) multi_heap_free_impl at C:/esp/msys32/esp/esp-idf/components/heap/multi_heap.c:395 (discriminator 1)

0x4008285e: heap_caps_free at C:/esp/msys32/esp/esp-idf/components/heap/heap_caps.c:190

0x40082c95: _free_r at C:/esp/msys32/esp/esp-idf/components/newlib/syscalls.c:42

0x400f43b9: tcp_close_shutdown at C:/esp/msys32/esp/esp-idf/components/lwip/core/tcp.c:1641

0x400f447b: tcp_close at C:/esp/msys32/esp/esp-idf/components/lwip/core/tcp.c:1641

0x4011cae6: lwip_netconn_do_close_internal at C:/esp/msys32/esp/esp-idf/components/lwip/api/api_msg.c:1740 (discriminator 6)

0x4011d8cf: lwip_netconn_do_close at C:/esp/msys32/esp/esp-idf/components/lwip/api/api_msg.c:1806

0x400fae31: tcpip_thread at C:/esp/msys32/esp/esp-idf/components/lwip/api/tcpip.c:474

Here is my code:

Code: Select all

#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "freertos/portmacro.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "tcpip_adapter.h"
#include "lwip/priv/api_msg.h"
#include "lwip/sockets.h"
#include "lwip/tcp.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/api.h"
#include "lwip/err.h"
#include "lwip/ip_addr.h"
#include "lwip/netbuf.h"
#include "lwip/netifapi.h"
#include "lwip/pppapi.h"
#include "string.h"
#include "cJSON.h"

#define LWIP_NETCONN_FULLDUPLEX 1
#define LWIP_NETCONN_SEM_PER_THREAD   1
#define LWIP_TCPIP_TIMEOUT   1

#define WEB_SERVER "api.thingspeak.com"
#define WEB_PORT 80
static const char WEB_URL_1[] = "GET https://api.thingspeak.com/update?api_key=";

static const char *TAG = "example";

static const char REQUEST[] = "HTTP/1.0\r\n"
    "Host: "WEB_SERVER"\r\n"
    "User-Agent: esp-idf/1.0 esp32\r\n"
    "\r\n";






SemaphoreHandle_t taskSemaphore = NULL;
char* json_unformatted;
static EventGroupHandle_t wifi_event_group;
const int CONNECTED_BIT = BIT0;
//static char* TAG = "app_main";
bool sta_is_configured = false;
char* ssid;
char* pwd;
struct connection
{
  struct netconn conn;
  bool available;
};

struct connection conn_array[5];

struct channel
{
  char name[80];
  char data_str[80];
  int data_int;
  char api[80];
};

struct channel channel_list[10];

#define delay(ms) (vTaskDelay(ms/portTICK_RATE_MS))
char* json_unformatted;

const static char http_html_hdr[] =
    "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n";

const static char http_index_hml[] = "<!DOCTYPE html>"
      "<html>\n"
      "<head>\n"
      "  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n"
      "  <style type=\"text/css\">\n"
      "    html, body, iframe { margin: 0; padding: 0; height: 100%; }\n"
      "    iframe { display: block; width: 100%; border: none; }\n"
      "  </style>\n"
      "<title>HELLO ESP32</title>\n"
      "</head>\n"
      "<body>\n"
      "<h1>Hello World, from ESP32!</h1>\n"
      "</body>\n"
      "</html>\n";

char http_index_hml_sta_config[] = "<!DOCTYPE html>"
      "<html>\n"
      "<head>\n"
      "<title>HELLO ESP32</title>\n"
      "</head>\n"
      "<body>\n"
      "<h1>Hello World, from ESP32!</h1>\n"
      "<form name=\"myForm\" onsubmit=\"sendForm(); return false;\">\n"
      "SSID:<br><input type=\"text\" name=\"ssid\" value=\"\"><br>\n"
      "PASS:<br><input type=\"text\" name=\"pass\" value=\"\"><br>\n"
      "<input type=\"submit\" value=\"Zapisz\">\n"
      "</form><br>\n"
      "<script>\n"
      "function sendForm() {\n"
      "var x = document.forms[\"myForm\"][\"ssid\"].value;\n"
      "var y = document.forms[\"myForm\"][\"pass\"].value;\n"
      "var xhttp = new XMLHttpRequest();\n"
      "xhttp.onreadystatechange = function() {\n"
      "if (this.readyState == 4 && this.status == 200) {\n"
      "location.reload(true);\n"
      "}\n"
      "};\n"
      "var url = \"?ssid=\"+x+\"&pass=\"+y;\n"
      "xhttp.open(\"GET\", url, true);\n"
      "xhttp.send();\n"
      "document.forms[\"myForm\"].reset()};\n"
      "</script>\n"
      "</body>\n"
      "</html>\n";

char http_index_hml_tmp[] = "<!DOCTYPE html>"
      "<html style=\"height: 100%;\">\n"
      "<body style=\"color:white; background:linear-gradient(141deg, #0fb8ad 0%, #1fc8db 51%, #2cb5e8 75%);\">\n"
      "<title>HELLO ESP32</title>\n"
      "</head>\n"
      "<body>\n"
      "<h1>Hello World, from ESP32!</h1>\n"
      "<form name=\"myForm\" onsubmit=\"sendForm(); return false;\">\n"
      "Kanal:<br><input type=\"text\" name=\"channel_add\" value=\"\"><br>\n"
      "Api:<br><input type=\"text\" name=\"api\" value=\"\"><br>\n"
      "<input type=\"submit\" value=\"Dodaj kanal\">\n"
      "</form><br>\n"
      "<div style=\"float: left; width: 15%;\">\n"
      "Kanal:\n"
      "<ul id = \"channel\"> </ul>\n"
      "</div>\n"
      "<div style=\"float: left; width: 15%;\">\n"
      "Pomiary:\n"
      "<ul id = \"data\" style=\"list-style: none;\"> </ul>\n"
      "</div>\n"
      "<div style=\"float: left; width: 15%;\">\n"
      "Usun kanal:\n"
      "<ul id = \"delete_ch\" style=\"list-style: none;\"> </ul>\n"
      "</div>\n"
      "<script>\n"
      "function jsonreq(){\n"
      "var xhttp = new XMLHttpRequest();\n"
      "xhttp.onreadystatechange = function() {\n"
      "if (this.readyState == 4 && this.status == 200) {\n"
      "obj = JSON.parse(this.responseText);\n"
      "var outleft = \"\";\n"
      "var outright = \"\";\n"
      "var delete_ch = \"\";\n"
      "var i;\n"
      "for(i = 0; i < obj.length; i++) {\n"
        "outleft += \"<li>\"+obj[i].Name +\"</li>\";\n"
        "outright += \"<li>\"+obj[i].Data +\"&nbsp\"+\"</li>\";\n"
        "delete_ch += \"<li><button type=\\\"button\\\" onclick =\\\"deleteCh(this); return false;\\\" id=\\\"\"+obj[i].Name+\"\\\">Usun</button></li>\";\n"
      "}\n"
      "document.getElementById(\"channel\").innerHTML = outleft;\n"
      "document.getElementById(\"data\").innerHTML = outright;\n"
      "document.getElementById(\"delete_ch\").innerHTML = delete_ch;\n"
      " }\n };\n"
      "xhttp.open(\"GET\", \"&\", true);\n"
      "xhttp.send();\n };"
      "function deleteCh(elem) {\n"
      "var x = elem.id\n"
      "var xhttp = new XMLHttpRequest();\n"
      "var url = \"?channel_del=\"+x\n"
      "xhttp.onreadystatechange = function() {\n"
      "if (this.readyState == 4 && this.status == 200) {\n"
      "jsonreq();}}\n"
      "xhttp.open(\"GET\", url, true);\n"
      "xhttp.send();\n"  
      "};\n"
      "function sendForm() {\n"
      "var x = document.forms[\"myForm\"][\"channel_add\"].value;\n"
      "var y = document.forms[\"myForm\"][\"api\"].value;\n"
      "var xhttp = new XMLHttpRequest();\n"
      "var url = \"?channel_add=\"+x+\"&api=\"+y;\n"
      
      "document.forms[\"myForm\"].reset()\n"
      "xhttp.onreadystatechange = function() {\n"
      "if (this.readyState == 4 && this.status == 200) {\n"
      "jsonreq(); }}\n"
      "xhttp.open(\"GET\", url, true);\n"
      "xhttp.send();\n"
      "};\n"
      "setInterval(jsonreq,10000);\n"
      "</script>\n </body>\n </html>\n";




static void generate_json() {
  cJSON *root, *d;
  
  root = cJSON_CreateArray();

  for(int i = 0;i<10;i++)
    {
      
      if(channel_list[i].name[0] != 0)
      {
      cJSON_AddItemToArray(root, d = cJSON_CreateObject());
      cJSON_AddStringToObject(d, "Name", channel_list[i].name);
      cJSON_AddStringToObject(d, "Data", channel_list[i].data_str);
      }
    }
         
  json_unformatted = cJSON_PrintUnformatted(root);

  printf("[len = %d]  ", strlen(json_unformatted));
  printf("%s\n", json_unformatted);


}





static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch(event->event_id) {
    case SYSTEM_EVENT_STA_START:
        esp_wifi_connect();
        break;
    case SYSTEM_EVENT_STA_GOT_IP:
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
        printf("got ip\n");
        printf("ip: " IPSTR "\n", IP2STR(&event->event_info.got_ip.ip_info.ip));
        printf("netmask: " IPSTR "\n", IP2STR(&event->event_info.got_ip.ip_info.netmask));
        printf("gw: " IPSTR "\n", IP2STR(&event->event_info.got_ip.ip_info.gw));
        printf("\n");

        fflush(stdout);
        break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
        /* This is a workaround as ESP32 WiFi libs don't currently
           auto-reassociate. */
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
        break;
    default:
        break;
    }
    return ESP_OK;
}

static void initialise_wifi(void)
{
    tcpip_adapter_init();
   

    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_AP) );
    
      


    wifi_config_t  ap_config = 
   {
    .ap = 
      {
      .ssid = "czesc",
      .password = "12345678",
      .authmode = WIFI_AUTH_WPA_WPA2_PSK,
      .ssid_len = 0,
      .beacon_interval = 400,
      .max_connection = 16,
      }
    };
  
    ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &ap_config) );
  //  
    ESP_ERROR_CHECK( esp_wifi_start() );
}

static void wifi_apsta_start()
{

  
  ESP_ERROR_CHECK( esp_wifi_stop() );
  esp_wifi_deinit();

  wifi_config_t  ap_config = 
   {
    .ap = 
      {
      .ssid = "czesc",
      .password = "12345678",
      .authmode = WIFI_AUTH_WPA_WPA2_PSK,
      .ssid_len = 0,
      .max_connection = 16,
      }
    };


  wifi_config_t  sta_config = 
   {
    .sta = 
      {
      .ssid = "",
      .password = "",
      .bssid_set = false,
      }
    };
    printf("ruraj123\n");
    strcpy(&sta_config.sta.ssid,ssid);
    strcpy(&sta_config.sta.password,pwd);
   
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
   
    printf("tutaj12\n");
    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_APSTA) );
    ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config) );
    ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &ap_config) );
    
    ESP_ERROR_CHECK( esp_wifi_start() );

    
}




static void http_get_task(int id)
{
    const struct addrinfo hints = {
        .ai_family = AF_INET,
        .ai_socktype = SOCK_STREAM,
    };
    struct addrinfo *res;
    struct in_addr *addr;
    int s, r;
    char recv_buf[64];
    char request[256];
    strcpy(request,WEB_URL_1);
    strcat(request,channel_list[id].api);
    strcat(request,"&field1=");
    strcat(request,channel_list[id].data_str);
    strcat(request,REQUEST);


    while(1) {
        /* Wait for the callback to set the CONNECTED_BIT in the
           event group.
        */
        
        int err = getaddrinfo(WEB_SERVER, "80", &hints, &res);

        if(err != 0 || res == NULL) {
            ESP_LOGE(TAG, "DNS lookup failed err=%d res=%p", err, res);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            continue;
        }

        /* Code to print the resolved IP.

           Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
        addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
        ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", inet_ntoa(*addr));

        s = socket(res->ai_family, res->ai_socktype, 0);
        if(s < 0) {
            ESP_LOGE(TAG, "... Failed to allocate socket.");
            freeaddrinfo(res);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            continue;
        }
        ESP_LOGI(TAG, "... allocated socket");

        if(connect(s, res->ai_addr, res->ai_addrlen) != 0) {
            ESP_LOGE(TAG, "... socket connect failed errno=%d", errno);
            close(s);
            freeaddrinfo(res);
            vTaskDelay(4000 / portTICK_PERIOD_MS);
            continue;
        }

        ESP_LOGI(TAG, "... connected");
        freeaddrinfo(res);

        if (write(s, request, strlen(request)) < 0) {
            ESP_LOGE(TAG, "... socket send failed");
            close(s);
            vTaskDelay(4000 / portTICK_PERIOD_MS);
            continue;
        }
        ESP_LOGI(TAG, "... socket send success");

        struct timeval receiving_timeout;
        receiving_timeout.tv_sec = 5;
        receiving_timeout.tv_usec = 0;
        if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &receiving_timeout,
                sizeof(receiving_timeout)) < 0) {
            ESP_LOGE(TAG, "... failed to set socket receiving timeout");
            close(s);
            vTaskDelay(4000 / portTICK_PERIOD_MS);
            continue;
        }
        ESP_LOGI(TAG, "... set socket receiving timeout success");

        /* Read HTTP response */
        
        close(s);
        
        break;
    }

vTaskDelete(NULL);
}


static void
http_server_netconn_serve(struct netconn* newconn)
{
  struct netconn conn_temp = *newconn;
  struct netconn* conn = &conn_temp;
  printf("%d\n", esp_get_free_heap_size());
  struct netbuf *inbuf;
  char  *buf;
  u16_t buflen;

  char* buf_temp = malloc(sizeof(char)*80);
  char* ChannelToAddMeasure = malloc(sizeof(char)*80);
  /* Read the data from the port, blocking if nothing yet there.
   We assume the request (the part we care about) is in one netbuf */
   netconn_write(conn, http_html_hdr, sizeof(http_html_hdr)-1, NETCONN_NOCOPY);
  
  if (netconn_recv(conn, &inbuf) == ERR_OK) {
  netbuf_data(inbuf,(void**)&buf,&buflen);
   

    /* Is this an HTTP GET command? (only check the first 5 chars, since
    there are other formats for GET, and we're keeping it very simple )*/
    printf("buffer = %s \n", buf);
    printf("buflen = %d\n", buflen);

   
    if (buflen>=5 && buf[0]=='G' && buf[1]=='E' && buf[2]=='T' && buf[3]==' ' && buf[4]=='/' && buf[5]=='&' )
    {
        generate_json();
        printf("po funkcji\n");
        netconn_write(conn, json_unformatted, strlen(json_unformatted), NETCONN_NOCOPY);
        free(json_unformatted);
        printf("po write\n");
        printf("po free\n");
    }
    else if (buflen>=5 && buf[0]=='G' && buf[1]=='E' && buf[2]=='T' && buf[3]==' ' && buf[4]=='/' && buf[5]=='!' )
     {
        int HTTP_pos=6;
        int measure_pos=0;
        int liczba;
        int ChannelToAddMeasurePos=0;
        memset(buf_temp,0,sizeof(char)*80);
        memset(ChannelToAddMeasure,0,sizeof(char)*80);
        printf("tutaj\n");

        while(buf[HTTP_pos]!='H')
        {
          HTTP_pos+=1;
        }

        printf("tutaj1\n");
        strncpy(buf_temp,strstr(buf,"channel_add=")+sizeof(char)*12,sizeof(char)*(HTTP_pos-19));
        printf("%s\n", buf_temp);
        printf("tutaj2\n");
        while(buf_temp[measure_pos]!=':')
        {
          measure_pos+=1;
        }
  
        strncpy(ChannelToAddMeasure,buf_temp,sizeof(char)*measure_pos);

        printf("%s\n",ChannelToAddMeasure);
        
        
        while(strcmp(channel_list[ChannelToAddMeasurePos].name,ChannelToAddMeasure)!=0)
        {
          ChannelToAddMeasurePos+=1;
          if(ChannelToAddMeasurePos>10)
          {
            break;
          }
        }
        if(ChannelToAddMeasurePos<10)
        {
       
        strcpy(ChannelToAddMeasure,buf_temp+measure_pos+1);
        printf("%s\n", ChannelToAddMeasure);
        liczba = strtol(ChannelToAddMeasure,NULL,10);
        printf("liczba= %d\n", liczba-1);
         strcpy(channel_list[ChannelToAddMeasurePos].data_str,ChannelToAddMeasure);
         xTaskCreate(&http_get_task, "http_get_task", 4096, ChannelToAddMeasurePos, 1, NULL);
       
    }
  }
  else if (buflen>=5 && buf[0]=='G' && buf[1]=='E' && buf[2]=='T' && buf[3]==' ' && buf[4]=='/' && buf[5]=='?' && sta_is_configured) {
        int and_pos=6;
        int HTTP_pos=6;
        int FemptyPos=0;
        memset(buf_temp,0,sizeof(char)*80);
        printf("tutaj\n");
        if(strstr(buf,"channel_add=") != NULL)
        {
        while(buf[and_pos] != '&')
          {
            and_pos+=1;
          }



        while(buf[HTTP_pos] != 'H')
        {
          HTTP_pos+=1;
        }

        strncpy(buf_temp,strstr(buf,"channel_add=")+sizeof(char)*12,sizeof(char)*(and_pos-18));

        while(channel_list[FemptyPos].name[0] != 0 && strcmp(channel_list[FemptyPos].name,buf_temp) != 0)
        {
          FemptyPos+=1;
        }
        
        printf("slowo = %s\n", buf_temp);
        printf("%d\n", FemptyPos);
        strcpy(channel_list[FemptyPos].name ,buf_temp);
        strncpy(channel_list[FemptyPos].api,strstr(buf,"api=")+sizeof(char)*4,sizeof(char)*(HTTP_pos-(and_pos+6)));
        for(int k = 0;k<=FemptyPos;k++)
        {
          printf("%s\n",channel_list[k].name );
          printf("%s\n",channel_list[k].api );
        }
        }
        else if(strstr(buf,"channel_del=") != NULL)
        {
          printf("Jestem tutaj \n");



        while(buf[HTTP_pos] != 'H')
        {
          HTTP_pos+=1;
        }

        strncpy(buf_temp,strstr(buf,"channel_del=")+sizeof(char)*12,sizeof(char)*(HTTP_pos-19));
        printf("buffer %s\n", buf_temp);
        while(strcmp(channel_list[FemptyPos].name,buf_temp) != 0)
        {
          FemptyPos+=1;
          if(FemptyPos > 10)
          {
            break;
          }
        }
        if(FemptyPos<10){
        printf("slowo = %s\n", buf_temp);
        printf("%d\n", FemptyPos);
        memset(channel_list[FemptyPos].name,0,80);
        memset(channel_list[FemptyPos].api,0,80);
        netconn_write(conn, "usunieto", 8, NETCONN_NOCOPY);
        } 
       
        }

     
      
    }
  else if (buflen>=5 && buf[0]=='G' && buf[1]=='E' && buf[2]=='T' && buf[3]==' ' && buf[4]=='/' && buf[5]=='?' && !sta_is_configured) {
        int and_pos=6;
        printf("tutaj");
        int HTTP_pos = 0;
        ssid = malloc(sizeof(char)*80);
        pwd = malloc(sizeof(char)*80);
        memset(ssid,0,sizeof(char)*80);
        memset(pwd,0,sizeof(char)*80);

        
        while(buf[and_pos] != '&')
          {
            and_pos+=1;
          }
          printf("tutaj1");
        strncpy(ssid,strstr(buf,"ssid=")+sizeof(char)*5,sizeof(char)*(and_pos-11));
        
        while(buf[HTTP_pos] != 'H')
          {
            HTTP_pos+=1;
          }
          printf("tutaj2");
        strncpy(pwd,strstr(buf,"pass=")+sizeof(char)*5,sizeof(char)*(HTTP_pos-(and_pos+7)));
        printf("ssid= %s\n", ssid);
        printf("haslo= %s\n",pwd );
        sta_is_configured = true;
        wifi_apsta_start(); 
        printf("po apppp\n");
        free(ssid);
        free(pwd);
    }
    else
    {
      if(!sta_is_configured) {netconn_write(conn, http_index_hml_sta_config, sizeof(http_index_hml_sta_config)-1, NETCONN_NOCOPY);}
      else {netconn_write(conn, http_index_hml_tmp, sizeof(http_index_hml_tmp)-1, NETCONN_NOCOPY);}
    }
   
  }
  printf("Przed close\n");
  err_t err1;
  // Close the connection (server closes in HTTP) 
  err1 = netconn_close(conn);

  printf("Po close, err = %d\n",err1);

  err1 = netconn_delete(conn);
  printf("Po delete, err = %d\n",err1);

  
  /* Delete the buffer (netconn_recv gives us ownership,
   so we have to make sure to deallocate the buffer) */
  //free(inbuf);

  //netbuf_free(inbuf);
  netbuf_delete(inbuf);
  free(buf_temp);
  free(ChannelToAddMeasure);
  printf("%d\n", esp_get_free_heap_size());
  vTaskDelete(NULL);
}

static void http_server(void *pvParameters)
{
  struct netconn *conn, *newconn;
  taskSemaphore = xSemaphoreCreateMutex();
  err_t err;
  conn = netconn_new(NETCONN_TCP);
  netconn_bind(conn, NULL, 80);
  netconn_listen(conn);
  do {
      err = netconn_accept(conn,&newconn);
            newconn->recv_timeout = 100;
            xTaskCreate(&http_server_netconn_serve,"http_server_netconn_serve",4096,newconn,5,NULL);
            //free(newconn);
            
        
        

   } while(err == ERR_OK);
   netconn_close(conn);
   netconn_delete(conn);
    vTaskDelete(NULL);
}



int app_main(void)
{
    nvs_flash_init();
    esp_wifi_restore();
    initialise_wifi();
    for(int i = 0;i<5;i++)
    {
      conn_array[i].available=true;
    }
    xTaskCreate(&http_server, "http_server", 4096, NULL, 5, NULL);
    return 0;
}
Maybe someone know what is wrong ?
Thanks in advance


ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: CORRUPT HEAP in multithread webserver with netconn API

Postby ESP_Angus » Sun Oct 01, 2017 10:24 pm

I don't think is the same issue as that memory leak issue.

What's happened here is almost certainly some code somewhere has overflowed a buffer and corrupted the heap. The crash is happening in the TCP task when it goes to free some memory, but this is after the actual corruption happens (it's just when the system realises corruption has happened, it's the symptom not the cause). The actual corruption has happened somewhere else.

Suggest going over the documentation about heap corruption here:
https://esp-idf.readthedocs.io/en/lates ... -detection

This will help you narrow it down. In particular, you can call heap_caps_check_integrity(MALLOC_CAP_8BIT) at various points in your code. This will print an error as soon as the corruption has occured, so you can move the calls around to "triangulate" the piece of code which is causing corruption.

JKozlo
Posts: 3
Joined: Fri Sep 15, 2017 2:23 pm

Re: CORRUPT HEAP in multithread webserver with netconn API

Postby JKozlo » Mon Oct 02, 2017 12:12 pm

Thank you for your attention.

I put heap_caps_check_integrity(MALLOC_CAP_8BIT,true) in many place, but nothing new appeared in my monitor. I don't know am I use it in wrong way or heap corrupts in other place. If I understand correctly second argument is responsible for printing errors and this function print error and I don't have to use printf, ESP_LOGI, ESP_ERROR_CHECK or something like that.

Thanks in advance.

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: CORRUPT HEAP in multithread webserver with netconn API

Postby ESP_Angus » Mon Oct 02, 2017 10:10 pm

JKozlo wrote:Thank you for your attention.

I put heap_caps_check_integrity(MALLOC_CAP_8BIT,true) in many place, but nothing new appeared in my monitor. I don't know am I use it in wrong way or heap corrupts in other place. If I understand correctly second argument is responsible for printing errors and this function print error and I don't have to use printf, ESP_LOGI, ESP_ERROR_CHECK or something like that.
You understand it correctly. What you can probably infer is that the corruption happens at some point in time after the last call to heap_caps_check_integrity() passes (ie prints no errors and returns true) and the time when the CORRUPT HEAP crash happens.

Who is online

Users browsing this forum: No registered users and 150 guests