Possible memory leak in uploading to blob (CA-13)
Hi,
I am using the stable version (for IDF 3) of this repository. I found that I am constantly loosing between 30 and 40 bytes, each time the callback is triggered when uploading multiple chunks to a file.
The callback:
static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataCallback(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* context)
{
(void)context;
if (result == FILE_UPLOAD_OK)
{
if (data != NULL && size != NULL)
{
if(!last_block)
{
int num_written = -1;
ESP_LOGI(TAG_WiFi, "Free heap space: %d", esp_get_free_heap_size());
char tmp[12] = "aaaaaaaaaaa";
*data = (const uint8_t *) tmp;
if(num_written == -1)
{
ESP_LOGI(TAG_WiFi, "Block with size %d", UPLOAD_BLOCK_SIZE);
*size = UPLOAD_BLOCK_SIZE;
} else {
*size = num_written;
last_block = true;
}
} else {
*data = NULL;
*size = 0;
if(DEBUG) ESP_LOGI(TAG_WiFi, "Indicating upload is complete.");
}
}
else
{
// The last call to this callback is to indicate the result of uploading the previous data block provided.
// Note: In this last call, data and size pointers are NULL.
if(DEBUG) ESP_LOGI(TAG_WiFi, "Last call to getDataCallback (result: %s)", ENUM_TO_STRING(IOTHUB_CLIENT_FILE_UPLOAD_RESULT, result));
}
}
else
{
ESP_LOGE(TAG_WiFi, "Received unexpected result %s", ENUM_TO_STRING(IOTHUB_CLIENT_FILE_UPLOAD_RESULT, result));
}
// To abort the upload, it should return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT
return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK;
}
And this is the code that initializes the upload:
bool synch_with_azure(void)
{
bool success = true;
(void)IoTHub_Init();
char * conn_string = <CONN-STRING>;
device_ll_handle = IoTHubDeviceClient_LL_CreateFromConnectionString(conn_string, HTTP_Protocol);
free(conn_string);
if (device_ll_handle == NULL)
{
ESP_LOGE(TAG_WiFi, "Failure creating Iothub device. Check conn string.");
}
else
{
IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_TRUSTED_CERT, certificates);
int num_unsynched = 1;
// Allocate the buffer that is used to synch the data. Size 512. Allocate in special memory.
if(tmp_upload_buffer == NULL) // Only allocate if it is NULL (has not been allocated)
{
tmp_upload_buffer = (uint8_t *) malloc(sizeof(uint8_t)*512);
}
if(tmp_upload_buffer != NULL)
{
ESP_LOGI(TAG_WiFi, "Successful allocation of upload buffer of size %d", UPLOAD_BLOCK_SIZE);
for(int i=0;i<num_unsynched;i++)
{
char file_name[9] = "test.txt; //64+32+puffer
if (IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob(device_ll_handle, file_name, getDataCallback, NULL) != IOTHUB_CLIENT_OK)
{
ESP_LOGE(TAG_WiFi, "Failed to upload");
success = false;
break;
}
else
{
if(DEBUG) ESP_LOGI(TAG_WiFi, "Successful upload.");
success = true;
}
}
free(tmp_upload_buffer);
}
if(!success)
{
ESP_LOGE(TAG_WiFi, "Unsuccessful upload. Calling abort_reading_data()");
}
IoTHubDeviceClient_LL_Destroy(device_ll_handle);
}
IoTHub_Deinit();
return success;
}
The output (using 1024 bytes for each upload rather than 512):
I (19715) Chaze-WIFI-Synch: Block with size 1024
I (19915) Chaze-WIFI-Synch: Free heap space: 17016
I (19915) Chaze-WIFI-Synch: Block with size 1024
I (20115) Chaze-WIFI-Synch: Free heap space: 16992
I (20115) Chaze-WIFI-Synch: Block with size 1024
I (20325) Chaze-WIFI-Synch: Free heap space: 16972
I (20325) Chaze-WIFI-Synch: Block with size 1024
I (20535) Chaze-WIFI-Synch: Free heap space: 16940
I (20535) Chaze-WIFI-Synch: Block with size 1024
I (20745) Chaze-WIFI-Synch: Free heap space: 16916
I (20745) Chaze-WIFI-Synch: Block with size 1024
I (20955) Chaze-WIFI-Synch: Free heap space: 16892
I (20955) Chaze-WIFI-Synch: Block with size 1024
I (21155) Chaze-WIFI-Synch: Free heap space: 16868
I (21155) Chaze-WIFI-Synch: Block with size 1024
I (21355) Chaze-WIFI-Synch: Free heap space: 16840
I (21355) Chaze-WIFI-Synch: Block with size 1024
I (21565) Chaze-WIFI-Synch: Free heap space: 16816
I (21565) Chaze-WIFI-Synch: Block with size 1024
I (21775) Chaze-WIFI-Synch: Free heap space: 16792
I (21775) Chaze-WIFI-Synch: Block with size 1024
I (21985) Chaze-WIFI-Synch: Free heap space: 16768
I (21985) Chaze-WIFI-Synch: Block with size 1024
I (22195) Chaze-WIFI-Synch: Free heap space: 16740
I (22195) Chaze-WIFI-Synch: Block with size 1024
I (22405) Chaze-WIFI-Synch: Free heap space: 16716
I (22405) Chaze-WIFI-Synch: Block with size 1024
I (22615) Chaze-WIFI-Synch: Free heap space: 16692
I (22615) Chaze-WIFI-Synch: Block with size 1024
I don't see that I am missing some malloc or anything else.
I am using the repo with the last commit 5f421bbd7ef8e6f5502204e9cd7a5f494070b39a with the commit message : Merge branch 'bugfix/big_chunk_read_fix' into 'master'
Are there any news regarding this?
I'm having the same issue, are there any updates?
@jubueche , sorry for the (very) late reply. Which example are you using? We do not have the file upload example in our examples/ folder. Are you using the samples from azure-iot-sdk-c/iothub_client/samples/?
Exactly. I am using https://github.com/Azure/azure-iot-sdk-c/blob/master/iothub_client/samples/iothub_client_sample_upload_to_blob_mb/iothub_client_sample_upload_to_blob_mb.c as a template. Thanks for your help!
Are you able to reproduce this issue? At this commit, the esp-azure repo is using azure-iot-sdk-c @ a0188ac . This is critical for us since our application is already running extremely low on memory and we can't afford a "small" mem leak.
@jubueche , we have updated azure-iot-c-sdk to LTS_06_2020_Ref01 . The azure sdk itself had some issues for file uploads, which are fixed in the latest version. Can you check again?
Everything seems to compile fine, but then this occurs:
Generating libwifi_synch.a.sections_info
Generating esp32.project.ld
LD build/app-template.elf
/home/julian/Documents/chaze-esp32/build/wifi_synch/libwifi_synch.a(wifi_synch.o):(.literal._Z16synch_with_azurev+0x4): undefined reference to `HTTP_Protocol'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(httpapiex.o):(.literal.HTTPAPIEX_ExecuteRequest+0x14): undefined reference to `HTTPAPI_Init'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(httpapiex.o):(.literal.HTTPAPIEX_ExecuteRequest+0x18): undefined reference to `HTTPAPI_CreateConnection'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(httpapiex.o):(.literal.HTTPAPIEX_ExecuteRequest+0x1c): undefined reference to `HTTPAPI_SetOption'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(httpapiex.o):(.literal.HTTPAPIEX_ExecuteRequest+0x20): undefined reference to `HTTPAPI_ExecuteRequest'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(httpapiex.o):(.literal.HTTPAPIEX_ExecuteRequest+0x24): undefined reference to `HTTPAPI_Deinit'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(httpapiex.o):(.literal.HTTPAPIEX_ExecuteRequest+0x28): undefined reference to `HTTPAPI_CloseConnection'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(httpapiex.o):(.literal.HTTPAPIEX_SetOption+0x4): undefined reference to `HTTPAPI_CloneOption'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(httpapiex.o): In function `HTTPAPIEX_ExecuteRequest':
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/c-utility/src/httpapiex.c:405: undefined reference to `HTTPAPI_Init'
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/c-utility/src/httpapiex.c:415: undefined reference to `HTTPAPI_CreateConnection'
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/c-utility/src/httpapiex.c:439: undefined reference to `HTTPAPI_SetOption'
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/c-utility/src/httpapiex.c:456: undefined reference to `HTTPAPI_ExecuteRequest'
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/c-utility/src/httpapiex.c:489: undefined reference to `HTTPAPI_Deinit'
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/c-utility/src/httpapiex.c:494: undefined reference to `HTTPAPI_CloseConnection'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(httpapiex.o): In function `HTTPAPIEX_Destroy':
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/c-utility/src/httpapiex.c:543: undefined reference to `HTTPAPI_CloseConnection'
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/c-utility/src/httpapiex.c:378: undefined reference to `HTTPAPI_Deinit'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(httpapiex.o): In function `HTTPAPIEX_SetOption':
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/c-utility/src/httpapiex.c:650: undefined reference to `HTTPAPI_CloneOption'
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/c-utility/src/httpapiex.c:680: undefined reference to `HTTPAPI_SetOption'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(iothub_client_ll_uploadtoblob.o):(.literal.IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl+0x70): undefined reference to `Blob_UploadMultipleBlocksFromSasUri'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(iothub_client_ll_uploadtoblob.o): In function `IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl':
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/iothub_client/src/iothub_client_ll_uploadtoblob.c:780: undefined reference to `Blob_UploadMultipleBlocksFromSasUri'
collect2: error: ld returned 1 exit status
/home/julian/esp/esp-idf/make/project.mk:482: recipe for target '/home/julian/Documents/chaze-esp32/build/app-template.elf' failed
make: *** [/home/julian/Documents/chaze-esp32/build/app-template.elf] Error 1
Do you know what could be the problem there?
[UPDATE] I have added
azure-iot-sdk-c/c-utility/adapters/httpapi_compact.o \
to component.mk and now the error messages are
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(iothub_client_ll_uploadtoblob.o):(.literal.IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl+0x70): undefined reference to `Blob_UploadMultipleBlocksFromSasUri'
/home/julian/Documents/chaze-esp32/build/esp-azure/libesp-azure.a(iothub_client_ll_uploadtoblob.o): In function `IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl':
/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/iothub_client/src/iothub_client_ll_uploadtoblob.c:780: undefined reference to `Blob_UploadMultipleBlocksFromSasUri'
collect2: error: ld returned 1 exit status
/home/julian/esp/esp-idf/make/project.mk:482: recipe for target '/home/julian/Documents/chaze-esp32/build/app-template.elf' failed
make: *** [/home/julian/Documents/chaze-esp32/build/app-template.elf] Error 1
It is compiling now. I had to add
azure-iot-sdk-c/iothub_client/src/blob.o \
azure-iot-sdk-c/iothub_client/src/iothubtransporthttp.o \
azure-iot-sdk-c/c-utility/adapters/httpapi_compact.o \
to component.mk.
But now I get the following error message:
Info: Waiting for TLS connection
Info: Waiting for TLS connection
Info: Waiting for TLS connection
Info: Waiting for TLS connection
Error: Time:Thu Jan 1 00:00:43 1970 File:/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/iothub_client/src/iothub_client_ll_uploadtoblob.c Func:send_http_sas_request Line:120 HTTP code was 401
Error: Time:Thu Jan 1 00:00:43 1970 File:/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/iothub_client/src/iothub_client_ll_uploadtoblob.c Func:IoTHubClient_LL_UploadToBlob_step1and2 Line:474 unable to HTTPAPIEX_ExecuteRequest
Error: Time:Thu Jan 1 00:00:43 1970 File:/home/julian/Documents/chaze-esp32/components/esp-azure/azure-iot-sdk-c/iothub_client/src/iothub_client_ll_uploadtoblob.c Func:IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl Line:772 error in IoTHubClient_LL_UploadToBlob_step1
Everything is working now, but the memory leak is still not gone. I suspect that the reason is not from Msft, but from ESP.
@jubueche , ok, we will check internally. Meanwhile, do you want to file a PR for the uploadToBlob example if you have it ready anyways?
Any news on this issue? I am currently seeing exactly the same behaviour as @jubueche.