memory leak fixed

This commit is contained in:
Sebastien
2020-02-24 16:14:17 -05:00
parent e3ea0c8140
commit e19c9e12dc
11 changed files with 92 additions and 88 deletions

View File

@@ -28,7 +28,8 @@
#include "platform_esp32.h"
#include "config.h"
#include "esp_sleep.h"
#include "driver/uart.h" // for the uart driver access
#include "driver/uart.h"
#include "messaging.h"
#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
#define WITH_TASKS_INFO 1
@@ -130,7 +131,7 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
if(it == NULL){
ESP_LOGE(TAG,"Unable initialize partition iterator!");
set_status_message(ERROR, "Reboot failed. Cannot iterate through partitions");
messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Reboot failed. Cannot iterate through partitions");
}
else
{
@@ -144,18 +145,19 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
if(err!=ESP_OK){
ESP_LOGE(TAG,"Unable to set partition as active for next boot. %s",esp_err_to_name(err));
bFound=false;
set_status_message(ERROR, "Unable to select partition for reboot.");
messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Unable to select partition for reboot.");
}
else{
ESP_LOGW(TAG, "Application partition %s sub type %u is selected for boot", partition->label,partition_subtype);
bFound=true;
set_status_message(WARNING, "Rebooting!");
messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Reboot failed. Cannot iterate through partitions");
}
}
else
{
ESP_LOGE(TAG,"partition type %u not found! Unable to reboot to recovery.",partition_subtype);
set_status_message(ERROR, "Partition not found.");
messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"partition type %u not found! Unable to reboot to recovery.",partition_subtype);
}
ESP_LOGD(TAG, "Yielding to other processes");
taskYIELD();

View File

@@ -14,6 +14,7 @@
#include "nvs_utilities.h"
#include "platform_esp32.h"
#include "messaging.h"
#include "trace.h"
/************************************
* Globals
*/
@@ -137,12 +138,12 @@ cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle){
else {
json_message = cJSON_CreateObject();
cJSON_AddStringToObject(json_message, "message", message->message);
vRingbufferReturnItem(buf_handle, (void *)message);
cJSON_AddStringToObject(json_message, "type", messaging_get_type_desc(message->type));
cJSON_AddStringToObject(json_message, "class", messaging_get_class_desc(message->msg_class));
cJSON_AddNumberToObject(json_message,"sent_time",message->sent_time);
cJSON_AddNumberToObject(json_message,"current_time",esp_timer_get_time() / 1000);
cJSON_AddItemToArray(json_messages,json_message);
vRingbufferReturnItem(buf_handle, (void *)message);
}
}
return json_messages;

View File

@@ -29,8 +29,9 @@
#include "esp_spi_flash.h"
#include "sdkconfig.h"
#include "messaging.h"
#include "trace.h"
#include "esp_ota_ops.h"
extern const char * get_certificate();
#ifdef CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1
@@ -57,16 +58,12 @@ typedef enum {
OTA_TYPE_INVALID
} ota_type_t;
static struct {
char status_text[81];
uint32_t actual_image_len;
uint32_t total_image_len;
uint32_t remain_image_len;
char * redirected_url;
char * current_url;
ota_type_t ota_type;
char * bin;
bool bOTAStarted;
bool bInitialized;
uint8_t lastpct;
uint8_t newpct;
struct timeval OTA_start;
@@ -99,10 +96,22 @@ void sendMessaging(messaging_types type,const char * fmt, ...){
if(str_len>0){
msg_str = malloc(str_len);
vsnprintf(msg_str,str_len,fmt,args);
if(type == MESSAGING_WARNING){
ESP_LOGW(TAG,"%s",msg_str);
}
else if (type == MESSAGING_ERROR){
ESP_LOGE(TAG,"%s",msg_str);
}
else
ESP_LOGI(TAG,"%s",msg_str);
}
else {
ESP_LOGW(TAG, "Sending empty string message");
}
va_end(args);
cJSON_AddStringToObject(msg,"ota_dsc",msg_str);
cJSON_AddStringToObject(msg,"ota_dsc",str_or_unknown(msg_str));
free(msg_str);
cJSON_AddNumberToObject(msg,"ota_pct", ota_get_pct_complete() );
char * json_msg = cJSON_PrintUnformatted(msg);
@@ -150,7 +159,7 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
case HTTP_EVENT_ON_CONNECTED:
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
if(ota_status.bOTAStarted) sendMessaging(MESSAGING_INFO,"Installing...");
if(ota_status.bOTAStarted) sendMessaging(MESSAGING_INFO,"Connecting to URL...");
ota_status.total_image_len=0;
ota_status.actual_image_len=0;
ota_status.lastpct=0;
@@ -165,9 +174,7 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
case HTTP_EVENT_ON_HEADER:
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s",evt->header_key, evt->header_value);
if (strcasecmp(evt->header_key, "location") == 0) {
FREE_RESET(ota_status.redirected_url);
ota_status.redirected_url=strdup(evt->header_value);
ESP_LOGW(TAG,"OTA will redirect to url: %s",ota_status.redirected_url);
ESP_LOGW(TAG,"OTA will redirect to url: %s",evt->header_value);
}
if (strcasecmp(evt->header_key, "content-length") == 0) {
ota_status.total_image_len = atol(evt->header_value);
@@ -191,7 +198,6 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
esp_err_t init_config(ota_thread_parms_t * p_ota_thread_parms){
memset(&ota_config, 0x00, sizeof(ota_config));
ota_status.bInitialized = true;
sendMessaging(MESSAGING_INFO,"Initializing...");
ota_status.ota_type= OTA_TYPE_INVALID;
if(p_ota_thread_parms->url !=NULL && strlen(p_ota_thread_parms->url)>0 ){
@@ -208,14 +214,14 @@ esp_err_t init_config(ota_thread_parms_t * p_ota_thread_parms){
switch (ota_status.ota_type) {
case OTA_TYPE_HTTP:
ota_status.current_url= p_ota_thread_parms->url;
ota_config.cert_pem =get_certificate();
ota_config.event_handler = _http_event_handler;
ota_config.buffer_size = BUFFSIZE;
ota_config.disable_auto_redirect=false;
ota_config.disable_auto_redirect=true;
ota_config.skip_cert_common_name_check = false;
ota_config.url = strdup(ota_status.current_url);
ota_config.url = strdup(p_ota_thread_parms->url);
ota_config.max_redirection_count = 3;
ota_write_data = heap_caps_malloc(ota_config.buffer_size+1 , MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
//ota_write_data = malloc(ota_config.buffer_size+1);
if(ota_write_data== NULL){
@@ -295,14 +301,14 @@ esp_err_t _erase_last_boot_app_partition(esp_partition_t *ota_partition)
if(i%2) {
sendMessaging(MESSAGING_INFO,"Erasing flash (%u/%u)",i,num_passes);
}
vTaskDelay(200/ portTICK_PERIOD_MS); // wait here for a short amount of time. This will help with reducing WDT errors
//vTaskDelay(200/ portTICK_PERIOD_MS); // wait here for a short amount of time. This will help with reducing WDT errors
}
if(remain_size>0){
err=esp_partition_erase_range(ota_partition, ota_partition->size-remain_size, remain_size);
if(err!=ESP_OK) return err;
}
sendMessaging(MESSAGING_INFO,"Erasing flash complete.");
taskYIELD();
return ESP_OK;
}
@@ -321,28 +327,32 @@ static bool process_again(int status_code)
static esp_err_t _http_handle_response_code(esp_http_client_handle_t http_client, int status_code)
{
esp_err_t err=ESP_OK;
if (status_code == HttpStatus_MovedPermanently || status_code == HttpStatus_Found) {
if (status_code == HttpStatus_MovedPermanently || status_code == HttpStatus_Found ) {
ESP_LOGW(TAG, "Handling HTTP redirection. ");
err = esp_http_client_set_redirection(http_client);
if (err != ESP_OK) {
ESP_LOGE(TAG, "URL redirection Failed. %s", esp_err_to_name(err));
return err;
}
ESP_LOGW(TAG, "Done Handling HTTP redirection. ");
} else if (status_code == HttpStatus_Unauthorized) {
ESP_LOGW(TAG, "Handling Unauthorized. ");
esp_http_client_add_auth(http_client);
}
ESP_LOGD(TAG, "Redirection done, checking if we need to read the data. ");
if (process_again(status_code)) {
char * local_buff = heap_caps_malloc(ota_config.buffer_size+1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
ESP_LOGD(TAG, "We have to read some more data. Allocating buffer size %u",ota_config.buffer_size+1);
char local_buff_var[501]={};
//char * local_buff = heap_caps_malloc(ota_config.buffer_size+1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
//char * local_buff = malloc(ota_config.buffer_size+1);
if(local_buff==NULL){
ESP_LOGE(TAG,"Failed to allocate internal memory buffer for http processing");
return ESP_ERR_NO_MEM;
}
// if(local_buff==NULL){
// ESP_LOGE(TAG,"Failed to allocate internal memory buffer for http processing");
// return ESP_ERR_NO_MEM;
// }
while (1) {
ESP_LOGD(TAG, "Reading data chunk. ");
int data_read = esp_http_client_read(http_client, local_buff, ota_config.buffer_size);
ESP_LOGD(TAG, "Buffer successfully allocated. Reading data chunk. ");
int data_read = esp_http_client_read(http_client, local_buff_var, sizeof(local_buff_var));
if (data_read < 0) {
ESP_LOGE(TAG, "Error: SSL data read error");
err= ESP_FAIL;
@@ -353,7 +363,7 @@ static esp_err_t _http_handle_response_code(esp_http_client_handle_t http_client
break;
}
}
FREE_RESET(local_buff);
//FREE_RESET(local_buff);
}
return err;
@@ -379,8 +389,6 @@ static esp_err_t _http_connect(esp_http_client_handle_t http_client)
status_code = esp_http_client_get_status_code(http_client);
ESP_LOGD(TAG, "HTTP status code was %d",status_code);
err = _http_handle_response_code(http_client, status_code);
if (err != ESP_OK) {
return err;
@@ -395,11 +403,7 @@ void ota_task_cleanup(const char * message, ...){
va_start(args, message);
sendMessaging(MESSAGING_ERROR,message, args);
va_end(args);
ESP_LOGE(TAG, "%s",ota_status.status_text);
}
FREE_RESET(ota_status.redirected_url);
FREE_RESET(ota_status.current_url);
FREE_RESET(ota_status.bin);
FREE_RESET(ota_write_data);
if(ota_http_client!=NULL) {
@@ -603,7 +607,7 @@ esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t
if(bin_url){
ota_thread_parms.url =strdup(bin_url);
ESP_LOGI(TAG, "Starting ota on core %u for : %s", OTA_CORE,bin_url);
ESP_LOGI(TAG, "Starting ota on core %u for : %s", OTA_CORE,ota_thread_parms.url);
}
else {
ota_thread_parms.bin = bin_buffer;
@@ -614,8 +618,7 @@ esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t
char * num_buffer=config_alloc_get(NVS_TYPE_STR, "ota_stack");
if(num_buffer!=NULL) {
stack_size= atol(num_buffer);
free(num_buffer);
num_buffer=NULL;
FREE_AND_NULL(num_buffer);
}
else {
ESP_LOGW(TAG,"OTA stack size config not found");
@@ -624,8 +627,7 @@ esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t
num_buffer=config_alloc_get(NVS_TYPE_STR, "ota_prio");
if(num_buffer!=NULL) {
task_priority= atol(num_buffer);
free(num_buffer);
num_buffer=NULL;
FREE_AND_NULL(num_buffer);
}
else {
ESP_LOGW(TAG,"OTA task priority not found");

View File

@@ -38,7 +38,7 @@
#include "config.h"
#include "nvs_utilities.h"
#include "platform_esp32.h"
#include "trace.h"
/************************************
* Globals
@@ -148,12 +148,14 @@ static void telnet_task(void *data) {
int rc = bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
if (rc < 0) {
ESP_LOGE(tag, "bind: %d (%s)", errno, strerror(errno));
close(serverSocket);
return;
}
rc = listen(serverSocket, 5);
if (rc < 0) {
ESP_LOGE(tag, "listen: %d (%s)", errno, strerror(errno));
close(serverSocket);
return;
}
@@ -171,6 +173,7 @@ static void telnet_task(void *data) {
ESP_LOGD(tag, "Telnet connection terminated");
}
}
close(serverSocket);
vTaskDelete(NULL);
}

View File

@@ -28,5 +28,20 @@
#define STR(macro) QUOTE(macro)
#endif
#define ESP_LOG_DEBUG_EVENT(tag,e) ESP_LOGD(tag,"evt: " e)
#ifndef STR_OR_ALT
#define STR_OR_ALT(str,alt) (str?str:alt)
#endif
extern const char unknown_string_placeholder[];
extern const char * str_or_unknown(const char * str);
#ifndef FREE_AND_NULL
#define FREE_AND_NULL(x) if(x) { free(x); x=NULL; }
#endif
#ifndef CASE_TO_STR
#define CASE_TO_STR(x) case x: return STR(x); break;
#endif
#define START_FREE_MEM_CHECK(a) size_t a=heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
#define CHECK_RESET_FREE_MEM_CHECK(a,b) ESP_LOGV(__FUNCTION__ ,b "Mem used: %i",a-heap_caps_get_free_size(MALLOC_CAP_INTERNAL)); a=heap_caps_get_free_size(MALLOC_CAP_INTERNAL)

View File

@@ -8,6 +8,6 @@
#
COMPONENT_EMBED_FILES := style.css code.js index.html bootstrap.min.css.gz jquery.min.js.gz popper.min.js.gz bootstrap.min.js.gz
COMPONENT_ADD_INCLUDEDIRS := .
CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_INFO
CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG

View File

@@ -51,6 +51,7 @@ function to process requests, decode URLs, serve files, etc. etc.
#include "lwip/ip_addr.h"
#include "messaging.h"
#include "platform_esp32.h"
#include "trace.h"
#define HTTP_STACK_SIZE (5*1024)
const char str_na[]="N/A";
@@ -148,6 +149,7 @@ char * http_alloc_get_socket_address(httpd_req_t *req, u8_t local, in_port_t * p
int s = httpd_req_to_sockfd(req);
if(s == -1) {
free(ipstr);
return strdup("httpd_req_to_sockfd error");
}
ESP_LOGV_LOC(TAG,"httpd socket descriptor: %u", s);
@@ -239,24 +241,31 @@ bool is_captive_portal_host_name(httpd_req_t *req){
/* Custom function to free context */
void free_ctx_func(void *ctx)
{
START_FREE_MEM_CHECK(ff);
session_context_t * context = (session_context_t *)ctx;
if(context){
ESP_LOGD(TAG, "Freeing up socket context");
FREE_AND_NULL(context->auth_token);
FREE_AND_NULL(context->sess_ip_address);
free(context);
CHECK_RESET_FREE_MEM_CHECK(ff,"free_ctx");
}
}
session_context_t* get_session_context(httpd_req_t *req){
START_FREE_MEM_CHECK(ff);
if (! req->sess_ctx) {
ESP_LOGD(TAG,"New connection context. Allocating session buffer");
req->sess_ctx = malloc(sizeof(session_context_t));
memset(req->sess_ctx,0x00,sizeof(session_context_t));
req->free_ctx = free_ctx_func;
// get the remote IP address only once per session
}
session_context_t *ctx_data = (session_context_t*)req->sess_ctx;
FREE_AND_NULL(ctx_data->sess_ip_address);
ctx_data->sess_ip_address = http_alloc_get_socket_address(req, 0, &ctx_data->port);
ESP_LOGD_LOC(TAG, "serving %s to peer %s port %u", req->uri, ctx_data->sess_ip_address , ctx_data->port);
CHECK_RESET_FREE_MEM_CHECK(ff,"get sess context");
return (session_context_t *)req->sess_ctx;
}
@@ -1043,25 +1052,34 @@ esp_err_t redirect_ev_handler(httpd_req_t *req){
esp_err_t messages_get_handler(httpd_req_t *req){
ESP_LOGD_LOC(TAG, "serving [%s]", req->uri);
START_FREE_MEM_CHECK(before);
START_FREE_MEM_CHECK(all);
if(!is_user_authenticated(req)){
// todo: redirect to login page
// return ESP_OK;
}
CHECK_RESET_FREE_MEM_CHECK(before, "after user auth");
esp_err_t err = set_content_type_from_req(req);
if(err != ESP_OK){
return err;
}
CHECK_RESET_FREE_MEM_CHECK(before, "after set_content_type");
cJSON * json_messages= messaging_retrieve_messages(messaging);
CHECK_RESET_FREE_MEM_CHECK(before, "after receiving messages");
if(json_messages!=NULL){
char * json_text= cJSON_Print(json_messages);
CHECK_RESET_FREE_MEM_CHECK(before, "after json print");
httpd_resp_send(req, (const char *)json_text, strlen(json_text));
cJSON_free(json_messages);
CHECK_RESET_FREE_MEM_CHECK(before, "after http send");
free(json_text);
CHECK_RESET_FREE_MEM_CHECK(before, "after free json message");
cJSON_free(json_messages);
CHECK_RESET_FREE_MEM_CHECK(before, "after free json");
}
else {
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR , "Unable to retrieve messages");
}
CHECK_RESET_FREE_MEM_CHECK(all, "before returning");
return ESP_OK;
}

View File

@@ -60,6 +60,7 @@ Contains the freeRTOS task and all necessary support
#include "config.h"
#include "trace.h"
#include "cmd_system.h"
#include "messaging.h"
#include "http_server_handlers.h"
#include "monitor.h"
@@ -850,20 +851,6 @@ void wifi_manager_connect_async(){
wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_USER);
}
void set_status_message(message_severity_t severity, const char * message){
if(ip_info_cjson==NULL){
ip_info_cjson = wifi_manager_get_new_json(&ip_info_cjson);
}
if(ip_info_cjson==NULL){
ESP_LOGE(TAG, "Error setting status message. Unable to allocate cJSON.");
return;
}
cJSON * item=cJSON_GetObjectItem(ip_info_cjson, "message");
item = wifi_manager_get_new_json(&item);
cJSON_AddItemToObject(item, "severity", cJSON_CreateString(severity==INFO?"INFO":severity==WARNING?"WARNING":severity==ERROR?"ERROR":"" ));
cJSON_AddItemToObject(item, "text", cJSON_CreateString(message));
}
char* wifi_manager_alloc_get_ip_info_json(){
return cJSON_PrintUnformatted(ip_info_cjson);
@@ -1142,6 +1129,7 @@ void wifi_manager( void * pvParameters ){
if(esp_wifi_scan_start(&scan_config, false)!=ESP_OK){
ESP_LOGW(TAG, "Unable to start scan; wifi is trying to connect");
// set_status_message(WARNING, "Wifi Connecting. Cannot start scan.");
messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Wifi connecting. Cannot start scan.");
}
else {
xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_SCAN_BIT);

View File

@@ -124,7 +124,7 @@ esp_err_t http_server_start()
strlcpy(rest_context->base_path, "/res/", sizeof(rest_context->base_path));
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.max_uri_handlers = 20;
config.max_uri_handlers = 25;
config.max_open_sockets = 5;
config.uri_match_fn = httpd_uri_match_wildcard;
//todo: use the endpoint below to configure session token?