Strtok causing "Assertion Failure" LED sequence

Hey,

Just wondering if anyone else has come across this issue since the upgrade from 0.7.0 to 1.0.1.

strtok is causing “Assertion Failure” red LED sequence (SOS 10 blinks SOS) when called since updating my electron from 0.7.0 to 1.0.1

the following is called in an ISR where RX_DATA is an array of data received from an external wireless module.
unfortunately since updating i get the red SOS message as soon as the code hits strtok.

    char * pt;
    pt = strtok(RX_DATA, ",");
    if (pt != NULL) {
      for (i = 0; i < 12; i++) {
        strcpy(DATA[i], pt);

        pt = strtok(NULL, ",");
      }
    }

Has anyone else noticed this issue?

many thanks,
P

I’m pretty sure strtok is not safe to use from an ISR.

I saw one mention that it uses malloc internally, which may or may not be true. If true, then it’s not safe to call from an ISR.

But also it’s definitely not reentrant and thus not safe to call from an ISR.

If the problem is only the reentrancy, using strtok_s might work, but I have not tried it. If the problem is memory allocation, then that probably won’t help.

3 Likes

Thanks Rick,
mmh where can I get strtok_s? - getting the not declared in this scope error.
I have
#include <string.h>
#include <stdio.h>
included…

Is it possible to use strings in an interrupt?
I have code running on 100+ devices at 0.7.0 without issue but since updating to 1.0.1 my code freaks out at strtok and where I use my string…

Even if you don’t expect it, but you should guard your for() loop against too short input.
I’d at least add this …

      for (i = 0; i < 12 && pt; i++) {

… to bail out when there are no more tokens to find.

I wouldn’t expect strtok() to use dynamic memory allocation (unless in a rather exotic implementation) since it usually manipulates the string in place, that’s why you need a non-const string to tokenise.
And the reentrant version of strtok() is char* strtok_r(char*, const char*, char**) (POSIX / C11)

strtok_s() stands for thread safeness but isn’t (currently) available on Particle devices.

However, I’d not perform string tokenisation in an ISR anyhow.

Having said that, have you thought about using sscanf()? (although I’d also think twice before doing that in an ISR)

3 Likes

thanks for the info. I’ll work on that and get back.

The main reason I want to tokenize the array in the ISR is that I also send a wireless acknowledgement to the sensor that sent the data so that it can go back to sleep as soon as possible. I need to figure out which sensor sent the data so I need to extract a sensor ID from the data point. and then send that to the wireless module.

Leaving aside the strtok for a moment. Even after removing strtok, the String I use to assemble the acknowledgement is causing the same Red SOS issue. if I remove all references to the strtok and the string, things seem to run ok.

Any idea why this might be the case?

bearing in mind that if I reflash 0.7.0 to my test electron, all these issues go away.

Does this mean you do that from the ISR too?
Maybe it’s not the strtok() that causes the SOS panic but the sending of the acknowledgement.
Can you show more of your code?

WIth that info it sounds as if you were running into a race condition where one of your global objects is invoking a not-yet instantiated secondary object.
This is an issue we have recently seen more frequently and is a side effect of some changes introduced some time ago with 0.8.0-rc.x.
The fact that it was running with 0.7.0 may rather be proof that 0.7.0 was too forgiving with some malpractices but 0.8.0-rc.x has put an end to that “oversight”.

Cool, you’re probably right. I think I need to waaaaayyy simplify my ISR code down to data collection from the bus and set a flag to trigger sending an ACK. then actually send the ACK in the main loop.
Does that sound ok?

I always knew that I had too much stuff in the ISR but I felt sending the ACK from there was the fastest way to get my sensor nodes to get to sleep and therefore reduce battery life.

1 Like

You are talking microseconds there - if you need to squeeze your battery that hard, you probably should reconsider the entire design :wink:

1 Like

haha yeah you’re right!! I’ll do that an put a message in here if it fixes my issues.
Thanks,
P

just to clear this up.

I vastly reduced the amount of code executing in the interrupt and that resolved my issues.

3 Likes