Page 1 of 1

callback function call results in InstrFetchProhibited

Posted: Wed Jul 14, 2021 3:49 am
by haddow777
Hello all, I'm fairly new to all this. I am having the most difficult time doing what seems to be a simple task. I have searched all over, used every technique I found and it all keeps ending up with this massive failure.

So, I am using an exp-WROOM-32S development board through vscode platformio (I figured the vscode discussion was for vscode specific problems, so I thought since it's seems to be a purely on board issue, it should go in this channel. Let me know if this question would.be better served elsewhere.

To start off, my code is quite simple at the moment. I include the ArduinoWebsockets library along with WiFi library. When I interfaced directly with the websocket library, everything worked perfectly. My board was independently talking with my remote node server no problem.

I then broke up the main big file into smaller files so as the project grows, it will be manageable. Part of that process was my wanting to abstract away the websocket functionality from the communication logic, in case down the line I decide to change or add more communication technologies. ArduinoWebsockets informs the program of an incoming message by having you register a callback function. The code example used a lambda function to do this like this:

Code: Select all

client.onMessage([&](WebsocketsMessage message){
        Serial.print("Got Message: ");
        Serial.println(message.data());
    });
So, part of the abstraction was to remove the need for the communications class to deal with the websockets specific WebsocketsMessage struct. so here is a very cut down simplified version of what I intended to do:

client_sockets.cpp

Code: Select all

void Websocket::onMessage(std::function<void()> cb) {
    client.onMessage([&](WebsocketsMessage message){
        Serial.print("Got Message: ");
        try {
            cb();
        } catch (const char* msg) {
            Serial.printf("%msg");
        }
    });
}
client is a property of my Websocket class, which is a websockets::WebsocketsClient object.

communications.cpp

Code: Select all

ws.onMessage([]() {
        Serial.println("Communications callback fired");
    });
ws is a property of my Communications class. This function call is one of the few things in it's setup function.

You'll notice that I am currently not including any parameter values in my callback. I did have them, but cut them out in case they may be causing issues. It really just comes down to the fact that as soon as I call cb(), the thing breaks. Now, what I don't understand is, I am doing exactly what the ArduinoWebsockets library is doing. At first, my research had me using function pointers, but when I looked at how the ArduinoWebsockets library did there's, I change to the std::function method. Neither work.

I did try to not use the lambda function, but it won't even let me compile that way. I first tried making a member function of the communications class to pass along as the callback, but the debugger said that it wasn't compatible with std::function. I even tried this my last attempt:

Code: Select all

std::function <void()> t_cb = []{Serial.println("Communications callback fired!");};
    ws.onMessage(t_cb);
I cannot for the life of me even begin to see what is wrong here. Is it that I am calling a callback within.a callback? I'm new to programming for something with tight constraints like a microcontroller and I admit, I've been programming in far less restrictive languages like Javascript the last while, so my C++ is rusty. Still, this seems like a no brainer. Any help would be very much appreciated.

Here is what the terminal spit out. Everything runs fine until the "Got Message:" output just before I call cb(). Also, it says the exception is unhandled. I wrapped my call in a try catch and it still went unhandled. I'm guessing that's because the core panic thing initiating a reboot. No exception to handle after that?

Code: Select all

--- Available filters and text transformations: colorize, debug, default, direct, esp32_exception_decoder, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at http://bit.ly/pio-monitor-filters
--- Miniterm on /dev/cu.SLAB_USBtoUART  115200,8,N,1 ---
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
...Connected to Wifi, Connecting to server.
Connected!
Got Message: Guru Meditation Error: Core  1 panic'ed (InstrFetchProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x3ffc60b4  PS      : 0x00060630  A0      : 0x800d1b58  A1      : 0x3ffb1d70  
A2      : 0x3ffc60b4  A3      : 0x00000000  A4      : 0x3ffc1810  A5      : 0x3ffc60b4  
A6      : 0x00000000  A7      : 0x00000000  A8      : 0x800d0701  A9      : 0x3ffb1d50  
A10     : 0x3ffb1f4c  A11     : 0x3f400120  A12     : 0x3ffcb772  A13     : 0x00000000  
A14     : 0x00050023  A15     : 0x3ffb8058  SAR     : 0x00000010  EXCCAUSE: 0x00000014  
EXCVADDR: 0x3ffc60b4  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xfffffffc  

ELF file SHA256: 0000000000000000

Backtrace: 0x3ffc60b4:0x3ffb1d70 0x400d1b55:0x3ffb1dc0 0x400d247a:0x3ffb1e30 0x400d24d1:0x3ffb1e50 0x400d087d:0x3ffb1f50 0x400d0999:0x3ffb1f70 0x400d09e2:0x3ffb1f90 0x400d66fd:0x3ffb1fb0 0x400897ca:0x3ffb1fd0

Rebooting...
ets Jun  8 2016 00:22:57/code]

Re: callback function call results in InstrFetchProhibited

Posted: Tue Jul 27, 2021 12:12 am
by haddow777
Okay, so I worked at it a bit. Not sure if this is a great solution, but it works.

Code: Select all

void Websocket::onMessage(std::function<void()> callback) {
    cb = callback;
    client.onMessage([&](WebsocketsMessage message) {
        msg = message.c_str();
        Serial.println("In websockets callback");
        Serial.println(msg);
        Serial.println("Attempting communications callback function call");
        cb();
    });
}
So, it appears if I try to call directly the function passed, it disappeared from memory before the call. So, I save the callback function locally as a property of the object and then call that function from the callback being passed. I guess in this way it ensures the reference to the function isn't lost. It kind of throws me as I'm pretty sure this isn't the way it works in languages I'm used to, but I'm happy to find a solution and just move on with the code.

If anyone has any insights I may be overlooking, I would be glad to gain in understanding. Thank you.

Re: callback function call results in InstrFetchProhibited

Posted: Tue Jul 27, 2021 1:18 am
by ESP_Sprite
Agree that fixing that goes against most I know about C and C++ as well; it's not reference counted and unless a different thread specifically messes with the callback pointer memory, this shouldn't fix your problem. I'm wondering if there's some other bug that you just managed to suppress the symptoms of by doing this...