Page 1 of 1

app_main() memory model / multi-threading

Posted: Thu Nov 21, 2019 2:56 pm
by PeterR
Towards the end of my latest sprint I have gained a new, strange exception.
The sprint added a memory hungry library and so I have been forced to start using PSRAM. AFAIK PSRAM is only used by the new libary as will only be allocated if malloc size > 32K and I still have internal RAM left.

The exception happens in app_main() initialisation within CreateDataBase() (I do not see the "Created" output).
Partial code to illustrate placement of masking code relative to the exception point.

Code: Select all

printf("Creating data\n");
model = CreateDataBase();
printf("Created\n");              // Not seen when exception raised
broker = new DeviceBroker(interfaceProcessor, model);
view = new FrontPanelView(broker, model, hwci->Buttons(), hwci->Leds());
view->Start();

WebApplication *webApplication = new WebApplication(model, settings, broker, hwci);
webApplication->Start();

// Adding these lines avoids the exception
vTaskDelay((1000) / portTICK_PERIOD_MS);
volatile std::string modeString = GetDatabaseValue<std::string>(model, DeviceModelString);
My question is, why would extracting a value from the 'model' at the end of initialisation prevent an exception being raised during the model's creation?
'model' is supplied to both the Front Panel & WebApplication 'views' & so must have been created.

EDIT: I wrapped the data item creation process with a try/catch and the problem items are std::string.
Once I add the enabling line then I no longer get an exception.
Is this a library issue then e.g. using the item brings in the correct library?

Re: app_main() memory model / multi-threading

Posted: Thu Nov 21, 2019 11:45 pm
by ESP_Angus
Hi PeterR,

Sorry it's not really clear from your description what is going wrong.

Do you have an example of a backtrace and the type of exception thrown?

Re: app_main() memory model / multi-threading

Posted: Fri Nov 22, 2019 10:44 am
by PeterR
Hi, Thanks.
Enclosed is the exception trace. I have not been able to create a MCVE, there is a lot of code in the background.
The key point however is why/how can the precence/absense of code in a different compilation unit (EDIT: that has not run yet) enable/disable an exception?
I will add some explanation:
1) The exception is raised in CreateDataBase() which is in another compilation unit from app_main().
2) Adding/removing volatile 'std::string modeString = GetDatabaseValue<std::string>(model, DeviceModelString);' disables/enables the exception.
3) CreateDataBase() creates a set of Boost::any wrapped within the DataCell template class. Each item is created and then assigned a default value. The intent is to provide a set of subscription values as per a data model.
4) The exception is raised whilst the default value is being assigned (DataCell.hpp#99). This function compares existing value is compared with new value such that observers may be notified but only if not empty. The existing value is only retrieved (and so comparision should only happen) if the boost::any is not .empty().
DataCell.hpp#81 - (SetValue) _cellValue = proposedValue.GetValue<DataCellValueType>();
DataCell.hpp#99 (GetValue) - return boost::any_cast<DataCellValueType>(_cellValue);
5) CreateDataBase() creates many other item types including structures and classes. Only std::string items appear to be a problem as shown in the exception report.
6) Works within Visual Studio and has previously worked on ESP32. I am working through the differences.

It seems that boost::any .empty() failed for std::string & but works when I add another line in another compilation unit.
Which is weird. Stacks have been bumped to 10K and (when working) I use FreeRTOS stats to determine proper safe level.

Code: Select all

abort() was called at PC 0x4010972f on core 0
0x4010972f: __cxxabiv1::__terminate(void (*)()) at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/eh_terminate.cc:112


ELF file SHA256: b452b8f1eba2c9b9cce643b4ec98e3938c698dcada4ea88a7aa83df89522106a

Backtrace: 0x4008b768:0x3ffbe620 0x4008b9b1:0x3ffbe640 0x4010972f:0x3ffbe660 0x40109776:0x3ffbe680 0x400f015b:0x3ffbe6a0 0x400ebc87:0x3ffbe6c0 0x4010c
709:0x3ffbe700 0x4012ff2e:0x3ffbe730 0x401300fd:0x3ffbe7e0 0x401305cd:0x3ffbe810 0x400d7d82:0x3ffbe8b0 0x400d2464:0x3ffbe9c0 0x40091ac1:0x3ffbe9e0
0x4008b768: invoke_abort at C:/msys32/home/Pete/esp/esp-idf/components/esp32/panic.c:716

0x4008b9b1: abort at C:/msys32/home/Pete/esp/esp-idf/components/esp32/panic.c:716

0x4010972f: __cxxabiv1::__terminate(void (*)()) at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/eh_terminate.cc:112

0x40109776: std::terminate() at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/eh_terminate.cc:112

0x400f015b: __cxa_throw at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/eh_throw.cc:87

0x400ebc87: void boost::throw_exception<boost::bad_any_cast>(boost::bad_any_cast const&) at C:/msys32/home/Pete/esp/Application/esp32/components/third
-party/include/boost/throw_exception.hpp:70

0x4010c709: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const& boost::any_cast<std::__cxx11::basic_string<char, st
d::char_traits<char>, std::allocator<char> > const&>(boost::any&) at C:/msys32/home/Pete/esp/Application/esp32/components/third-party/include/boost/an
y.hpp:268

0x4012ff2e: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > boost::any_cast<std::__cxx11::basic_string<char, std::char
_traits<char>, std::allocator<char> > >(boost::any const&) at C:/msys32/home/Pete/esp/Application/esp32/components/third-party/include/boost/any.hpp:2
94
 (inlined by) std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > DataCell::GetValue<std::__cxx11::basic_string<char, std:
:char_traits<char>, std::allocator<char> > >() const at C:/msys32/home/Pete/esp/Application/esp32/components/database/include/DataCell.hpp:99
 (inlined by) bool DataCell::SetValue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<cha
r, std::char_traits<char>, std::allocator<char> > const&) at C:/msys32/home/Pete/esp/Application/esp32/components/database/include/DataCell.hpp:81
 (inlined by) DatabaseEntry<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::SetToDefault(DataRow*) const at C:/msys
32/home/Pete/esp/Application/esp32/components/Model/src/CreateDatabase.cpp:39

0x401300fd: CreateDataBaseRow(DataTable*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<IDatabaseEntryB
ase*, std::allocator<IDatabaseEntryBase*> > const&) at C:/msys32/home/Pete/esp/Application/esp32/components/Model/src/CreateDatabase.cpp:206

0x401305cd: GetSensor0DatabaseRow(DataTable*) at C:/msys32/home/Pete/esp/Application/esp32/components/Model/src/CreateDatabase.cpp:240

0x400d7d82: app_main at C:/msys32/home/Pete/esp/Application/esp32/main/app_main.cpp:355 (discriminator 3)

0x400d2464: main_task at C:/msys32/home/Pete/esp/esp-idf/components/esp32/cpu_start.c:529

0x40091ac1: vPortTaskWrapper at C:/msys32/home/Pete/esp/esp-idf/components/freertos/port.c:435


Rebooting...
ets Jun  8 2016 00:22:57

EDIT: Solved the second issue (above still needs a fix). Figured that sometimes exceptions were decoded but not always. Added a try/catch.