I am unable to establish a http server connection and MQTT connection at the same time on an ESP8266 (Nodemcu) using libraries ESPAsyncWebServer and PubSubClient. My intention is to push over the air updates using the library AsyncElegantOTA while at the same time using MQTT for something else. Everything works great until I attempt to establish the HTTP server connection using the method below: setup_http(). I have tried establishing the connection within setup but that fails immediately and the connection cycles repeatedly. So, I have attempted to establish the connection within the loop function but that is failing as well. Is it possible to run both in the same sketch?
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <time.h>
#include "Secrets.h"
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
#define IOT_PUBLISH_TOPIC "pubout"
#define IOT_SUBSCRIBE_TOPIC "subin"
bool isServerStarted = false;
time_t now;
time_t nowish = 1510592825;
BearSSL::X509List cert(cacert);
BearSSL::X509List client_crt(client_cert);
BearSSL::PrivateKey key(privkey);
WiFiClientSecure net;
PubSubClient client(net);
void NTPConnect(void)
{
Serial.print("Setting time using SNTP");
configTime(TIME_ZONE * 3600, 0 * 3600, "pool.ntp.org", "time.nist.gov");
now = time(nullptr);
while (now < nowish)
{
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("done!");
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
Serial.print("Current time: ");
Serial.print(asctime(&timeinfo));
}
String get_wifi_status()
{
switch (WiFi.status())
{
case WL_IDLE_STATUS:
return String("Wifi is changing modes.");
break;
case WL_NO_SSID_AVAIL:
return String("SSID: '") + WIFI_SSID + " is not available.";
break;
case WL_CONNECTED:
return String("Connected to ") + WIFI_SSID;
break;
case WL_CONNECT_FAILED:
return String("Could not connect to ") + WIFI_SSID;
break;
case WL_DISCONNECTED:
return String("Wifi not in station mode.");
break;
default:
return String("Wifi status error");
}
}
void setup_network()
{
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
WiFi.mode(WIFI_STA);
Serial.println("");
while (WiFi.status() != WL_CONNECTED)
{
Serial.print("Connecting to ");
Serial.print(WIFI_SSID);
Serial.println("...");
delay(1000);
}
Serial.println(get_wifi_status());
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void messageReceived(char *topic, byte *payload, unsigned int length)
{
//handle messages
}
void setup_mqtt()
{
delay(3000);
NTPConnect();
net.setTrustAnchors(&cert);
net.setClientRSACert(&client_crt, &key);
client.setServer(MQTT_HOST, 8883);
client.setCallback(messageReceived);
Serial.println("Connecting to IOT");
while (!client.connect(THINGNAME))
{
Serial.print(".");
delay(1000);
}
if (!client.connected())
{
Serial.println("IoT Timeout!");
return;
}
// Subscribe to a topic
client.subscribe(IOT_SUBSCRIBE_TOPIC);
Serial.println("IoT Connected!");
}
void setup_http()
{
AsyncWebServer server(80);
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(200, "text/plain", "Hi! I am a http server."); });
server.begin();
AsyncElegantOTA.begin(&server); // Start ElegantOTA
Serial.println("HTTP server started");
}
void setup()
{
Serial.begin(115200);
setup_network();
setup_mqtt();
// setup_http(); //Does not work here and crashes before MQTT connects. So, I moved to loop but that doesn't work either.
}
void loop()
{
now = time(nullptr);
if (!client.connected())
{
setup_mqtt();
}
if (isServerStarted == false)
{
Serial.println("Attempting to start http server");
delay(3000);
setup_http();
isServerStarted = true;
Serial.println("It crashes before we get here");
}
else
{
client.loop();
// BEGIN Loop code
}
}
Exception:
User exception (panic/abort/assert)
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
Unhandled C++ exception: OOM
>>>stack>>>
ctx: cont
sp: 3ffffd20 end: 3fffffc0 offset: 0000
3ffffd20: 3fff199c 3fff169c 000000ff 00000000
3ffffd30: 000000fe 00000000 00000000 00000000
3ffffd40: 00000000 00000000 00000000 00000001
3ffffd50: 3fff3198 00000000 3fff31a4 00000000
3ffffd60: 00000000 402089c6 00000c08 4021f12e
3ffffd70: 00000000 00000020 00000c08 4021f14d
3ffffd80: 3fff63ec 402089c6 00000c08 4021e832
3ffffd90: 3ffffda0 3ffffdec 3ffffde4 402089c6
3ffffda0: cca8cca9 00000000 3fff4554 40208bd6
3ffffdb0: c0afc0ae c027c023 c028c024 c013c009
3ffffdc0: c014c00a c031c02d c032c02e 00000000
3ffffdd0: c02ac026 c00ec004 c00fc005 009d009c
3ffffde0: c09dc09c c0a1c0a0 003d003c 0035002f
3ffffdf0: c012c008 c00dc003 0000000a 4021e813
3ffffe00: 00000000 3ffffe9c 3ffffe94 3fff6804
3ffffe10: 00000000 00000000 3fff4554 40209108
3ffffe20: 3fff1698 00000000 00000000 4025ebd3
3ffffe30: 007a1200 3fff4554 00000040 4025a222
3ffffe40: 007a1200 32087824 00000000 00000000
3ffffe50: 00000000 00000000 00000000 00000000
3ffffe60: 40106105 002da5e3 3fff13d8 00000000
3ffffe70: 3fff0af0 3fff13d8 00000001 00000000
3ffffe80: 00000000 00000000 00000000 00000000
3ffffe90: 00000000 3ffffe9c 00000000 4021f24a
3ffffea0: 3ffe8ff8 3fff4554 3fff61ec 402074f2
3ffffeb0: 3ffffee0 00000000 3fff1ac0 00000001
3ffffec0: 000022b3 3fff4554 3ffe8ff8 00000001
3ffffed0: 000022b3 3fff4554 3ffe8ff8 402093b4
3ffffee0: 40224b24 b781db12 40224b24 b781db12
3ffffef0: 00000000 00000000 3fff0ff8 40222932
3fffff00: 00004b4f 3fff4554 3fff0ff8 4020426c
3fffff10: 00000002 3fff1218 3fff610c 40220395
3fffff20: 00000000 00000000 3ffe8e9c 00000000
3fffff30: 00000000 3fff1218 3ffe967c 4021bce0
3fffff40: 4021bcd4 3fff1218 3ffe967c 3fff1370
3fffff50: 3fffdad0 3fff4554 3fff1044 40204518
3fffff60: 00000000 00000000 00000001 4021c200
3fffff70: 40224b24 3fff4554 3fff1044 40201e97
3fffff80: 402039cc feefeffe 40222b18 40222afc
3fffff90: 3fffdad0 00000000 3ffe88e4 40201f15
3fffffa0: feefeffe feefeffe feefeffe 4021ebb7
3fffffb0: feefeffe feefeffe feefeffe 40101225
<<<stack<<<
0x402089c6 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >::__allocated_ptr(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&, std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0>*) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:53
(inlined by) std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:97
0x4021f12e in raise_exception at core_esp8266_postmortem.cpp:?
0x4021f14d in __unhandled_exception at ??:?
0x402089c6 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >::__allocated_ptr(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&, std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0>*) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:53
(inlined by) std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:97
0x4021e832 in operator new(unsigned int) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/abi.cpp:47
0x402089c6 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >::__allocated_ptr(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&, std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0>*) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:53
(inlined by) std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:97
0x40208bd6 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >::get() at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:85
(inlined by) std::__shared_count<(__gnu_cxx::_Lock_policy)0>::__shared_count<br_x509_minimal_context, std::allocator<br_x509_minimal_context>>(br_x509_minimal_context*&, std::_Sp_alloc_shared_tag<std::allocator<br_x509_minimal_context> >) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr_base.h:681
(inlined by) std::__shared_ptr<br_x509_minimal_context, (__gnu_cxx::_Lock_policy)0>::__shared_ptr<std::allocator<br_x509_minimal_context>>(std::_Sp_alloc_shared_tag<std::allocator<br_x509_minimal_context> >) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr_base.h:1371
(inlined by) std::shared_ptr<br_x509_minimal_context>::shared_ptr<std::allocator<br_x509_minimal_context>>(std::_Sp_alloc_shared_tag<std::allocator<br_x509_minimal_context> >) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr.h:408
(inlined by) std::shared_ptr<br_x509_minimal_context> std::allocate_shared<br_x509_minimal_context, std::allocator<br_x509_minimal_context>>(std::allocator<br_x509_minimal_context> const&) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr.h:860
(inlined by) std::shared_ptr<br_x509_minimal_context> std::make_shared<br_x509_minimal_context>() at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr.h:876
(inlined by) BearSSL::WiFiClientSecureCtx::_installClientX509Validator() at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.cpp:1063
0x4021e813 in operator new(unsigned int) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/abi.cpp:41
0x40209108 in BearSSL::WiFiClientSecureCtx::_connectSSL(char const*) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.cpp:1134
0x4025ebd3 in ip_chksum_pseudo at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/lwip2/builder/lwip2-src/src/core/inet_chksum.c:395
0x4025a222 in tcp_output at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/lwip2/builder/lwip2-src/src/core/tcp_out.c:1361
0x40106105 in ets_timer_arm_new at ??:?
0x4021f24a in delay at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_wiring.cpp:54
0x402074f2 in ClientContext::connect(ip4_addr*, unsigned short) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/include/ClientContext.h:148
(inlined by) WiFiClient::connect(IPAddress, unsigned short) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/WiFiClient.cpp:162
0x402093b4 in BearSSL::WiFiClientSecureCtx::connect(char const*, unsigned short) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.cpp:232
0x40224b24 in DhcpServer::add_end(unsigned char*) at ??:?
0x40224b24 in DhcpServer::add_end(unsigned char*) at ??:?
0x40222932 in BearSSL::WiFiClientSecure::connect(char const*, unsigned short) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.h:245
0x4020426c in PubSubClient::connect(char const*, char const*, char const*, char const*, unsigned char, bool, char const*, bool) at .pio\libdeps\nodemcu\PubSubClient\src/PubSubClient.cpp:190
0x40220395 in uart_write at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/uart.cpp:544
0x4021bce0 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:194
0x4021bcd4 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:191
0x40204518 in PubSubClient::connect(char const*) at .pio\libdeps\nodemcu\PubSubClient\src/PubSubClient.cpp:167
0x4021c200 in Print::println(char const*) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/Print.cpp:194
0x40224b24 in DhcpServer::add_end(unsigned char*) at ??:?
0x40201e97 in setup_mqtt() at src/main.cpp:133
0x402039cc in messageReceived(char*, unsigned char*, unsigned int) at src/main.cpp:114
0x40222b18 in std::_Function_handler<void (char*, unsigned char*, unsigned int), void (*)(char*, unsigned char*, unsigned int)>::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h:271
0x40222afc in std::_Function_handler<void (char*, unsigned char*, unsigned int), void (*)(char*, unsigned char*, unsigned int)>::_M_invoke(std::_Any_data const&, char*&&, unsigned char*&&, unsigned int&&) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h:289
0x40201f15 in setup at src/main.cpp:171
0x4021ebb7 in loop_wrapper() at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_main.cpp:198
0x40101225 in cont_wrapper at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/cont.S:81
last failed alloc call: 402089C6(3080)
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
last failed alloc caller: 0x402089c6
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 3460, room 16
tail 4
chksum 0xcc
load 0x3fff20b8, len 40, room 4
tail 4
chksum 0xc9
csum 0xc9
v000b9e90
~ld
In setup_http(), you declared server as a variable local to the function. That means when the function returns, the variable (and web server) will be destroyed, which will lead to some seriously undefined behavior, like a crash.
You need to make sure that server exists and is valid for the lifetime of the web server, so you should declare it outside of the function, as a global or static variable.
For instance,
AsyncWebServer server(80);
void setup_http()
{
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(200, "text/plain", "Hi! I am a http server."); });
server.begin();
...
This will ensure that server isn't destroyed while you're still using it.
I'm currently facing an issue with a vector iterator in C++. The application runs on an ESP8266 NodeMCU microcontroller. As soon as I call the function CWebServer::getAvailableNetworks() (implementation can be found below), the program crashes and I get the following error:
User exception (panic/abort/assert)
Abort called
>>>stack>>>
ctx: cont
sp: 3ffffd10 end: 3fffffc0 offset: 0000
3ffffd10: 00000000 00000000 00000000 00000000
3ffffd20: 000000fe 00000000 00000000 00000000
3ffffd30: 00000000 00000000 00000000 b8b1aabc
3ffffd40: 3ffefd60 3fff44cc 00000000 40205e9c
3ffffd50: 3fff451c 00000001 3fff44fc 4020e7ea
3ffffd60: 00000000 00000000 00000000 4020e7fc
3ffffd70: 00000000 3ffffe0c 00000000 4020e219
3ffffd80: 3ffffe04 00000000 00000000 00000000
3ffffd90: 00000000 00000000 00000000 40226fac
3ffffda0: 00000000 40205e9c 3fff451c 40226fbd
3ffffdb0: 3fff44fc 3fff44cc 3fff44fc 402277d8
3ffffdc0: 00000000 00000000 3fff44fc 4020e224
3ffffdd0: 40000000 00000000 00000000 00000000
3ffffde0: 00000000 00000000 00000000 40226fac
3ffffdf0: 3ffefb6c 40205e9c 3fff451c 40226fbd
3ffffe00: 3fff44fc 4022770c 3fff44fc 40227783
3ffffe10: 3fff451c 00000001 3ffffe80 40209f32
3ffffe20: 3ffe90e4 3fffc200 3ffe90f1 4022f3b3
3ffffe30: 3fff43dc 3ffefa4c 3ffe8a37 4020ca74
3ffffe40: 4020ca68 3ffefa4c 3ffe8a37 40205e9c
3ffffe50: 00000001 3ffffe8c 3ffe90e5 4022f3f6
3ffffe60: 3ffffe80 00000001 3ffefa4c 40205e9c
3ffffe70: 00000001 00000001 3ffefa4c 40209915
3ffffe80: 00000000 00000000 00000000 3fff43e8
3ffffe90: 00000001 00000001 00000020 401009b7
3ffffea0: 3fff3d4c 3fffff00 3ffffee0 40205e9c
3ffffeb0: 00000001 00000001 3fff3c54 4021837a
3ffffec0: 3fffff00 3ffef94c 3fff3c54 401000e1
3ffffed0: 3fff3c54 3ffef94c 3fff3c54 40205ed8
3ffffee0: 3fff3d00 0015001f 8015001f 80fe8614
3ffffef0: 3fff3c54 3ffef94c 3ffef90c 40208526
3fffff00: 3fff3d4c 0015001f 00c6a700 00000000
3fffff10: 807a1200 3fff4400 0000005f 80007641
3fffff20: 3ffef94c 00000001 402183ac 00000001
3fffff30: 00000001 00000000 00001388 4020bb3e
3fffff40: 00000000 3fff43a4 3ffef90c 3ffefac8
3fffff50: 00000001 3ffef930 3ffef90c 402093ec
3fffff60: 40218d50 00000000 00001388 4020ca74
3fffff70: 00000000 3fff43a4 3ffe8a37 4020cd39
3fffff80: 3fffdad0 00000000 3ffefa88 402094b0
3fffff90: 3fffdad0 00000000 3ffefa88 4020a140
3fffffa0: feefeffe feefeffe 3ffefa88 4020e454
3fffffb0: feefeffe feefeffe 3ffe8614 40100cb9
<<<stack<<<
ets Jan 8 2013,rst cause:1, boot mode:(3,7)
load 0x4010f000, len 3456, room 16
tail 0
chksum 0x84
csum 0x84
va5432625
~ld
Here is the function that causes the problem ():
void CWebServer::getAvailableNetworks()
{
Serial.println("Get network scan result.");
bool statusSend = false;
try
{
std::string output = "{\"networks\":";
std::vector<sWiFi_Data*> data = CWiFiConnection::getAvailableNetworks();
if(data.size() <= 0)
{
output += "{}";
}
for(std::vector<sWiFi_Data*>::iterator it = data.begin(); it != data.end(); ++it)
{
// This line is for testing. Later on the JSON output will be calculated here from the Vector.
Serial.println(((*it)->SSID).c_str());
}
output += "}";
statusSend = true;
server.send(200, "application/json", output.c_str());
} catch(ScanException& e)
{
statusSend = true;
server.send(425);
} catch(std::exception e)
{
statusSend = true;
server.send(500);
Serial.println();
Serial.println("Unknown Exception while getting the network data:");
Serial.println(e.what());
Serial.println();
}
if(!statusSend) server.send(500);
}
This function should send the results of a network scan to the client. The network scan is simply done by calling the function WiFi.scanNetworks(true, true); which is part of the ESP8266WiFi.
The problem is caused by the line Serial.println(((*it)->SSID).c_str());
As soon as the program gets to this point, the error will show up and the program crashes. If I just delete this line and don't touch the vector at all, everything runs fine. So I assume that the vector iterator is the bad guy here.
Just for completence: as you can see the vector stores pointer to structs of type "sWiFi_Data".
This struct is defined in another class (the class that handles the WiFi connection) and it looks like this:
struct sWiFi_Data
{
std::string SSID;
std::string BSSID;
int32_t RSSI;
uint8_t channel;
uint8_t encryptionType;
bool isHidden;
};
As you may have noticed inside the CWebServer::getAvailableNetworks() function, the vector is the result of another function ( CWiFiConnection::getAvailableNetworks(); ). This function is inside the CWiFiConnection class. It looks like this:
std::vector<sWiFi_Data*> CWiFiConnection::getAvailableNetworks()
{
std::vector<sWiFi_Data*> data;
int8_t n = WiFi.scanComplete();
if(n == -1) throw ScanException("Warning: Trying to access network scan data while scan is not completed yet.");
if(n == -2) throw ScanException("Warning: Trying to access network scan, but scan was never triggered.");
if(n >= 0)
{
for(int i = 0; i < n; i++)
{
uint8_t encrytptionType = 0;
switch(WiFi.encryptionType(i)) {
case ENC_TYPE_NONE:
encrytptionType = 1; // None, Open Network
case ENC_TYPE_WEP:
encrytptionType = 2; // WEP
case ENC_TYPE_TKIP:
encrytptionType = 3; // WPA
case ENC_TYPE_CCMP:
encrytptionType = 4; // WPA 2
case ENC_TYPE_AUTO:
encrytptionType = 5; // Auto
default:
encrytptionType = 0; // Unknown
}
sWiFi_Data wifiData;
wifiData.SSID = WiFi.SSID(i).c_str();
wifiData.BSSID = WiFi.BSSIDstr(i).c_str();
wifiData.RSSI = WiFi.RSSI(i);
wifiData.channel = WiFi.channel(i);
wifiData.encryptionType = encrytptionType;
wifiData.isHidden = WiFi.isHidden(i);
data.push_back(&wifiData);
}
WiFi.scanDelete();
return data;
} else
{
throw ScanException("Warning: No networks found.");
}
}
By the way: the ScanException is just a generic exception that I wrote. Nothing fancy so I don't think that I would need to include the code here.
And just to clarify things, the procedure of communication looks like this:
Client send request to scan networks.
Server just calls the method: WiFi.scanNetworks(true, true); (Parameters: bool async, bool showHidden)
Because the scan is asynchronous, the client checks the result by sending a request to the server.
The server always responds to these requests by calling the CWebServer::getAvailableNetworks() function (our problem function).
In theory this function should reply with a code 425 ("not ready yet") if the result isn't there yet and should send the data of all available networks as a JSON if the scan is finished (this will be implemented where the line Serial.println(((*it)->SSID).c_str()); currently is.
By the way: I also tried to just output the vector's size inside the console. This works fine. So there are definitely values inside the vector.
Hope that anyone can help me out here. Thanks a lot.
Jannis
ps.: A documentation with examples for the network scan on an ESP8266 can be found here: https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/scan-examples.html
This line: data.push_back(&wifiData); stores the address of a temporary object wifiData which will be destroyed once the scope, i.e the enclosing for-loop iteration, is exited.
When you then later access any of these addresses it will (probably) cause a seg fault (if you are lucky).
Instead of having a std::vector<sWiFi_Data*> better use a std::vector<sWiFi_Data>
I'm trying to write a kernel driver (module) that reads GPIO on a RPI3
I use ioremap to get access to the memory of the GPIO, but apparently it crashes.
I get an exception in the /var/log/messages log file
Aug 6 14:07:58 raspberrypi kernel: [ 220.900252] Exception stack(0xa796ffa8 to 0xa796fff0)
Aug 6 14:07:58 raspberrypi kernel: [ 220.900264] ffa0: fe5f5100 7eff8714 00000003 0002d064 00000000 00000004
Aug 6 14:07:58 raspberrypi kernel: [ 220.900277] ffc0: fe5f5100 7eff8714 0003fce8 0000017b 007e47d8 00000000 00000002 00000000
Aug 6 14:07:58 raspberrypi kernel: [ 220.900286] ffe0: 7eff8548 7eff8538 00022cb8 76cb9af0
Here is my module code:
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/io.h>
#define BCM2708_PERI_BASE 0x20000000
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
static int __init driver_init(void)
{
if ((gpio = ioremap(GPIO_BASE, 0xB0)) == NULL) {
printk(KERN_INFO "io remap failed\n");
return -EBUSY;
}
return 0;
}
static void __exit driver_exit(void)
{
iounmap(gpio);
}
module_init(driver_init);
module_exit(driver_exit);
Can someone tell me what I do wrong?
Is there a conflict with another driver? How can I check this?
base adress is 0x3F000000, not 0x2000000
I would like to create a Arduino library for an ESP8266or ESP32 microcontroller. I wrote a test library which running on an Arduino Nano board with no problem. Here the library cpp file:
#include "Test.h"
Test::Test(){
}
uint32_t Test::libTest(strcttest* t){
uint32_t w;
w = t->a;
return w;
}
Here's the the header file :
#include <Arduino.h>
typedef struct {
uint32_t a;
uint32_t b;
}strcttest;
class Test
{
public:
Test();
uint32_t libTest(strcttest* t);
private:
};
And last but not least the Arduino ino file:
#include <Test.h>
//Instante Test
Test t;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("Start");
}
void loop() {
// put your main code here, to run repeatedly:
//Create structure
strcttest *tt;
tt->a=1;
tt->b=2;
//Output result
Serial.println (t.libTest(tt));
delay(1000);
}
Every compile fine with an Arduino Nano board as well as with ESP8266/ESP32 boards. When I run it on the Nano Board i get the expected result:
Start
1
1
1
1
1
1
1
1
1
...
When I run it on the ESP8266 board I get the following crash result:
l*⸮⸮⸮⸮CI>⸮⸮⸮HB⸮⸮Start
Exception (28):
epc1=0x402024f8 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: cont
sp: 3ffef7d0 end: 3ffef9a0 offset: 01a0
>>>stack>>>
3ffef970: feefeffe 00000000 3ffee950 40201eb4
3ffef980: feefeffe feefeffe 3ffee96c 40202340
3ffef990: feefeffe feefeffe 3ffee980 40100108
<<<stack<<<
7!a!*6⸮⸮⸮Start
Exception (28):
epc1=0x402024f8 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: cont
sp: 3ffef7d0 end: 3ffef9a0 offset: 01a0
>>>stack>>>
3ffef970: feefeffe 00000000 3ffee950 40201eb4
3ffef980: feefeffe feefeffe 3ffee96c 40202340
3ffef990: feefeffe feefeffe 3ffee980 40100108
<<<stack<<<
ĜBs⸮`⸮"⸮⸮Start
...
And last but not least on the ESP Development board I receive:
i%M/⸮`⸮i%M7
⸮⸮%Q=qU=\Md⸮aGd<$⸮Start
Guru Meditation Error of type LoadProhibited occurred on core 1. Exception was unhandled.
Register dump:
PC : 0x400dde93 PS : 0x00060030 A0 : 0x800d0570 A1 : 0x3ffc7390
A2 : 0x3ffc1c30 A3 : 0x00000000 A4 : 0x0800001c A5 : 0xffffffff
A6 : 0xffffffff A7 : 0x00060d23 A8 : 0x800832e9 A9 : 0x3ffc7380
A10 : 0x00000003 A11 : 0x00060023 A12 : 0x00060020 A13 : 0x00000003
A14 : 0x00000001 A15 : 0x00000000 SAR : 0x0000001f EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Backtrace: 0x400dde93:0x3ffc7390 0x400d0570:0x3ffc73b0 0x400d79b0:0x3ffc73d0
CPU halted.
So my question is: What I am doing wrong. What do i miss. What I haven't understood with Arduino IDE, cpp, pointers, etc.
Sorry I forgot: I use Arduino IDE 1.8.2
strcttest *tt; is your problem. You're not allocating memory for and creating an object of type strcttest - you're merely allocating memory for a pointer to an object of that type. Basically, the code should crash everywhere when your code gets to the line tt->a=1; The fact that it doesn't when run on the Nano is basically dumb luck..
Think of the case where you have a char* variable and then try to copy a string to it - it will crash too, since you dont have any storage space for the string itself - you only have a few bytes allocated that store the address of the string.
The following is a more reasonable implementation of your void loop() function:
void loop() {
// put your main code here, to run repeatedly:
//Create structure
strcttest tt;
tt.a=1;
tt.b=2;
//Output result
Serial.println (t.libTest(&tt));
delay(1000);
}
Another (slower, due to use of new and delete) implementation may look like this:
void loop() {
// put your main code here, to run repeatedly:
//Create structure
strcttest *tt = new strcttest;
tt->a=1;
tt->b=2;
//Output result
Serial.println (t.libTest(tt));
delete tt;
delay(1000);
}
For ESP32 and ESP8266, have a excellent tool to help in crashes situations,
like that You report.
This integrates to Arduino IDE
See it in: https://github.com/me-no-dev/EspExceptionDecoder
TL;DR: is my guess of a DLL loader lock deadlock correct in this instance and how can I be sure?
I have an intermittent deadlock (50%) in some code that involves CRT time functions and National Instruments DAQmx drivers (9.3.5f2). I'm using MSVC2008 Express to create an x86 executable (typical "release" settings, can supply if required) and I'm running on Win7 Pro x64. My code uses the time functions on the main thread and starts a new thread to handle updating an analogue output voltage (on a USB-6009):
#include <iostream>
#include <ctime>
#include <windows.h>
#include <process.h>
#include <NIDAQmx.h>
HANDLE g_TerminateEvent;
extern "C" unsigned int WINAPI DacUpdateThreadRunner(void *lpParam)
{
TaskHandle taskHandle;
DAQmxCreateTask("", &taskHandle);
DAQmxCreateAOVoltageChan(taskHandle, "Dev2/ao0", "", 0.0, 3.3, DAQmx_Val_Volts, "");
DAQmxStartTask(taskHandle);
float64 sample_value = 0.0;
bool quit = false;
while (!quit)
{
DWORD wait_result = WaitForSingleObject(g_TerminateEvent, 32);
if (wait_result == WAIT_OBJECT_0) quit = true;
else
{
DAQmxWriteAnalogScalarF64(taskHandle, 1, 1.0, sample_value, NULL);
}
}
DAQmxStopTask(taskHandle);
DAQmxClearTask(taskHandle);
return 0;
}
int main(void)
{
g_TerminateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
unsigned int m_ThreadId;
uintptr_t m_Thread = _beginthreadex(NULL, 0, DacUpdateThreadRunner, NULL, 0, &m_ThreadId);
struct tm t;
time_t tt = time(NULL);
struct tm *temp = localtime(&tt);
memcpy(&t, temp, sizeof(struct tm));
for (int i = 0; i < 10; i++)
{
std::cout << "Main thread doing stuff " << i << std::endl;
Sleep(1000);
}
SetEvent(g_TerminateEvent);
CloseHandle((HANDLE)m_Thread);
return 0;
}
It only seems to deadlock if I have the call to localtime() in the code. Looking at the debug output in MSVS it seemed to lock while the 2nd thread was loading the (many) NI DLLs (the last DLLs to be loaded before the deadlock are National Instruments\MAX\mxs.dll, National Instruments\MAX\mxsutils.dll and SysWOW64\version.dll).
In the MSVC 2008 runtime localtime maps to localtime64() and apparently it uses thread local storage under Windows in order to be threadsafe.
I used WinDbg to get the call stacks (shown below) after the application deadlocked and used the !locks command but I cannot see why there would be a deadlock as I can't see any shared resource that both threads are locking. The locks command outputs Scanned 10 critical sections but nothing else (do I need to use a checked build of Windows?).
main thread:
ChildEBP RetAddr Args to Child
0035f078 77288df4 000001d0 00000000 00000000 ntdll_77250000!NtWaitForSingleObject+0x15
0035f0dc 77288cd8 00000000 00000000 00000000 ntdll_77250000!RtlpWaitOnCriticalSection+0x13e
0035f104 772a9520 773520c0 773271ca 0035f350 ntdll_77250000!RtlEnterCriticalSection+0x150
0035f144 751a1ee1 005e0000 0035f35c bf6b8258 ntdll_77250000!LdrGetDllHandleByMapping+0x3b
0035f304 751a1fd2 0035f350 0035f348 00000002 KERNELBASE!BasepLoadLibraryAsDataFileInternal+0x4f4
0035f324 751a2221 0035f350 0035f348 00000002 KERNELBASE!BasepLoadLibraryAsDataFile+0x19
0035f360 751993ad 0035f38c 00000000 006a7eb4 KERNELBASE!LoadLibraryExW+0x18a
0035f598 75199535 0035f630 72cbc018 00000002 KERNELBASE!ConvertTimeZoneMuiString+0xe4
0035f5bc 7519966b 0035f5d8 72cbbfc4 72cbc018 KERNELBASE!ConvertTimeZoneMuiStrings+0x155
0035f688 75199729 72cbbfc0 00000001 0035f6f0 KERNELBASE!GetTimeZoneInformationRaw+0x8c
0035f698 72c58d90 72cbbfc0 bf60abfe 0035f778 KERNELBASE!GetTimeZoneInformation+0xf
0035f6f0 72c59390 bf60aa2e 0035f778 00f625f8 MSVCR90!_set_timezone+0x168
0035f720 72c59e79 01103384 00f625f8 000001cc MSVCR90!__tzset+0x2e
0035f748 72c5a0b1 00f625f8 0035f778 00000001 MSVCR90!_localtime64_s+0x9f
0035f75c 01101107 0035f778 01103384 00000001 MSVCR90!_localtime64+0x1a
0035f784 011015e9 00000001 00f61850 00f62ba8 deadlock2!main+0x57 [c:\david\dev\nitests\deadlock2\deadlock2.cpp # 60]
0035f7c8 7509339a 7efde000 0035f814 77289ef2 deadlock2!__tmainCRTStartup+0x10f [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c # 586]
0035f7d4 77289ef2 7efde000 7732789a 00000000 KERNEL32!BaseThreadInitThunk+0xe
0035f814 77289ec5 01101731 7efde000 00000000 ntdll_77250000!__RtlUserThreadStart+0x70
0035f82c 00000000 01101731 7efde000 00000000 ntdll_77250000!_RtlUserThreadStart+0x1b
second thread:
ChildEBP RetAddr Args to Child
0276e618 77288df4 0000021c 00000000 00000000 ntdll_77250000!NtWaitForSingleObject+0x15
0276e67c 77288cd8 00000000 00000000 72c83b4e ntdll_77250000!RtlpWaitOnCriticalSection+0x13e
0276e6a4 72c42f2a 72cbbab8 0276e978 0276e6ec ntdll_77250000!RtlEnterCriticalSection+0x150
0276e6b4 72c48a70 00000007 bd23bbe2 00f69170 MSVCR90!_lock+0x30
*** ERROR: Symbol file could not be found. Defaulted to export symbols for mxsutils.dll -
0276e6ec 1b4fc523 0276e700 00000105 0276e978 MSVCR90!_getcwd+0x13
WARNING: Stack unwind information not available. Following frames may be wrong.
0276e80c 1b4fd45c 0276e81c 0276e9a4 1b5009e7 mxsutils!mxsCheckComponent+0x67c3
0276e838 1b515a05 0276e9a4 0276e978 00000000 mxsutils!mxsCheckComponent+0x76fc
0276e994 1b51542a 0276e9a4 00f619c0 0276e9b0 mxsutils!std::_Init_locks::operator=+0x1a4f
0276e9d8 1b502aa0 0276eaf0 00f69170 00f619c0 mxsutils!std::_Init_locks::operator=+0x1474
0276eb54 1b4f163f 00000001 00000001 006b0300 mxsutils!CodeProject3rdParty::mxs_mxExceptionFilter+0x320
0276eba8 1b502831 1b240000 1b529f40 00000001 mxsutils+0x163f
*** ERROR: Symbol file could not be found. Defaulted to export symbols for mxs.dll -
0276ebc8 1b2414e9 00000001 00000000 00f62540 mxsutils!CodeProject3rdParty::mxs_mxExceptionFilter+0xb1
0276edf8 1b24593c 1b240000 00000001 00000000 mxs+0x14e9
0276ee3c 1b2459f6 1b240000 0276ee68 77289950 mxs!std::_Init_locks::operator=+0x44c
0276ee48 77289950 1b240000 00000001 00000000 mxs!std::_Init_locks::operator=+0x506
0276ee68 7728d8c9 1b2459d8 1b240000 00000001 ntdll_77250000!LdrpCallInitRoutine+0x14
0276ef5c 7728d78c 00000000 75717046 00000000 ntdll_77250000!LdrpRunInitializeRoutines+0x26f
0276f0c8 7728c4d5 0276f12c 0276f0f4 00000000 ntdll_77250000!LdrpLoadDll+0x4d1
0276f100 751a2288 0276f0f4 0276f144 0276f12c ntdll_77250000!LdrLoadDll+0xaa
*** ERROR: Symbol file could not be found. Defaulted to export symbols for nidmxfu.dll -
0276f13c 6dd8b3ad 00000000 00000000 006b03fc KERNELBASE!LoadLibraryExW+0x1f1
0276f568 6dd8b4d3 0276f86c 6ded4a38 0276f92c nidmxfu!nNIMSAI100::tFilterPreferences::~tFilterPreferences+0x65cd
0276f584 6dc39d62 0276f6cc 0276f728 0276f870 nidmxfu!nNIMSAI100::tFilterPreferences::~tFilterPreferences+0x66f3
00000000 00000000 00000000 00000000 00000000 nidmxfu!nNIMS100::tAttributeDatabase::getAttributeValueForString+0x12432
My guess is that the main thread has locked an internal lock in the MSVCRT and then went to load a DLL which it cannot because thread 2 has a DLL loader lock. Thread 2 tries to use getcwd() from the MSVCRT which then results in the deadlock. Is that an accurate assessment? If not, how could I go about getting more information to make sure?
I could probably work around it by re-ordering some of the code (e.g. use wxDateTime or the NI code from the main thread to pre-load the DLLs) if I was confident that was the problem. However, I don't want to just hide it and have it re-appear and bite me later.
So is there a way for me to verify what has caused the deadlock in this case?
Your diagnosis is correct. tzset holds a lock while calling LoadLibrary. Meanwhile, _getcwd is waiting for that same lock. mxsutils is calling _getcwd from inside its DllMain. Like most functions, _getcwd is not safe to call from DllMain. A temporary workaround would be to make a dummy call to localtime from main before you create any threads. A long-term fix would be to change msxutils so it doesn't call unsafe functions from inside DllMain.
I notice that you are calling wxDateTime::Now() without doing any initialization of the wxWidgets system. My guess would be that wxDateTime::Now() is relying on something that is initialized when you do a normal wxWidgets initialization. Have you tried not even starting your other thread, but simply checking that wxDateTime::Now() works OK like this?
I also notice that you are using wxWidgets v2.9.2. Recommend you upgrade to v2.9.4. Apart from many improvements that might help your situation, these is a fix to a bug in wxDateTime. Might not help with current problem, but will fix a problem you don't yet know you have