Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Settings Utility and Example App #2178

Closed

Conversation

TimJTi
Copy link
Contributor

@TimJTi TimJTi commented Nov 4, 2023

Last year @fjpanag offered to donate some code to the repo. This is my attempt at making his "settings" functions NuttX compatible along with an example app to check it out
Impact

None. This is new.
Testing

On my custom board (SAMA5D27C-D1G). It seems to work!

There are probably still some style and/or NuttX-convention errors/inconsistencies so I have left it as a draft for now.

@TimJTi
Copy link
Contributor Author

TimJTi commented Nov 4, 2023

I have no idea why this is failing CI? HELP!

@TimJTi TimJTi marked this pull request as ready for review November 4, 2023 14:12
@TimJTi
Copy link
Contributor Author

TimJTi commented Nov 4, 2023

OK - I assume it's because a created a new "top level" folder (utils) for the settings functions rather than placing it under some pre-existing folder?

If someone can propose a good folder for it to be re-homed to I can do it, or the new folder needs to be added to the scripts, I think?

@TimJTi TimJTi force-pushed the Add-settings-utility-and-example-app branch from 6db40dd to 31d654a Compare November 4, 2023 17:37
@xiaoxiang781216
Copy link
Contributor

how about system/ folder? Many utility libraries put there.

@TimJTi TimJTi marked this pull request as draft November 5, 2023 12:17
@TimJTi TimJTi force-pushed the Add-settings-utility-and-example-app branch 3 times, most recently from 235000c to c725bc1 Compare November 5, 2023 13:26
@TimJTi
Copy link
Contributor Author

TimJTi commented Nov 5, 2023

@xiaoxiang781216 It still fails CI - I HAVE NO IDEA!!!!!!!!!!!

@TimJTi TimJTi force-pushed the Add-settings-utility-and-example-app branch 2 times, most recently from 865a2d6 to e1813e4 Compare November 5, 2023 15:41
@raiden00pl
Copy link
Member

raiden00pl commented Nov 6, 2023

@TimJTi when CI fails and you don't know what's going on, the most common problem is some error in Kconfig. For me configure with this PR shows:

CMake Warning at CMakeLists.txt:348 (message):
  Kconfig Configuration Error: warning: the default selection
  EXAMPLES_SETTINGS_CREATE_RAMDISK (undefined) of <choice> (defined at
  /home/raiden00/git/RTOS/nuttx/apps/examples/settings/Kconfig:31) is not
  contained in the choice

You're probably using kconfig-frontends which doesn't catch as many errors as kconfiglib used by CI

@TimJTi
Copy link
Contributor Author

TimJTi commented Nov 6, 2023

@TimJTi when CI fails and you don't know what's going on, the most common problem is some error in Kconfig. For me configure with this PR shows:

CMake Warning at CMakeLists.txt:348 (message):
  Kconfig Configuration Error: warning: the default selection
  EXAMPLES_SETTINGS_CREATE_RAMDISK (undefined) of <choice> (defined at
  /home/raiden00/git/RTOS/nuttx/apps/examples/settings/Kconfig:31) is not
  contained in the choice

You're probably using kconfig-frontends which doesn't catch as many errors as kconfiglib used by CI

Thank you! I will check.

It's a long time since I set up my Linux build environment but I will certainly look to see whether I use kconfig-frontends or kconfiglib and changeover if I can.

@TimJTi TimJTi force-pushed the Add-settings-utility-and-example-app branch from e1813e4 to 9a8b964 Compare November 6, 2023 11:15
@TimJTi
Copy link
Contributor Author

TimJTi commented Nov 6, 2023

@raiden00pl Tests are running now - thank you.

I edit Kconfig files in VS Code, and have a syntax checker extension, and have kconfig-frontends as per NuttX install/setup guides for Ubuntu.

I can pip install kconfiglib, but am not sure how to make use of it. Can you share your Kconfig edit/create workflow with me so I can avoid these errors in the future?

I am actually thinking VS Code may be a hindrance not a help - I find a build will fail within VSCode for reasons I can never see, usually to do with apps, and end up having to "force save" a new .config from make menuconfig and build from a terminal prompt before it all works OK again in VS Code.

May be time for me to jump ship to a different edit/build/debug workflow completely!!!!!!!!!!

@raiden00pl
Copy link
Member

In my case it was just installing python-kconfiglib package for my OS (I'm avoid pip installs when possible). Build system should auto-detect kconfiglib if available.
kconfiglib should make the menuconfig command available in your system, so you can check it with command -v menuconfig command which should return path to menuconfig command:

[raiden00:~/git/RTOS/nuttx/nuttx]$ command -v menuconfig                                                                               
/usr/bin/menuconfig

If this doesn't work, then probably the packages installed with pip (usually ~/.local/bin) are not in system PATH

@TimJTi
Copy link
Contributor Author

TimJTi commented Nov 6, 2023

@raiden00pl

In my case it was just installing python-kconfiglib package for my OS (I'm avoid pip installs when possible). Build system should auto-detect kconfiglib if available. kconfiglib should make the menuconfig command available in your system, so you can check it with command -v menuconfig command which should return path to menuconfig command:

Thank you - installed and working!

@TimJTi TimJTi marked this pull request as ready for review November 6, 2023 14:16
system/settings/storage_bin.c Outdated Show resolved Hide resolved
system/settings/storage_bin.c Outdated Show resolved Hide resolved
system/settings/storage_bin.c Outdated Show resolved Hide resolved
system/settings/storage_bin.c Outdated Show resolved Hide resolved
system/settings/storage_bin.c Outdated Show resolved Hide resolved
system/settings/storage_text.c Outdated Show resolved Hide resolved
system/settings/storage_text.c Outdated Show resolved Hide resolved
system/settings/storage_text.c Outdated Show resolved Hide resolved
system/settings/storage_text.c Outdated Show resolved Hide resolved
if ((g_settings.store[i].file[0] != '\0') &&
g_settings.store[i].save_fn)
{
ret = g_settings.store[i].save_fn(g_settings.store[i].file);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it isn't safe to call fs function in signal handler

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiaoxiang781216 - OK - will look tomorrow as need a clear mind for it :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found that as soon as I replied a few minutes ago so deleted it. Thanks :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xiaoxiang781216 If I have understood this right:

  1. Calls to the save function are obviously asynchronous
  2. Each call to the save function sets a a new timer
  3. That timer could trigger before the processing of a previous timer has completed. And that potentially violates the signal safety concern?

I have proven this to be an issue, to satisfy my curiosity by adding a sleep into the the save function and calling it a few times before the function awakens. It crashes, so - I hope - I've understood it?

@fjpanag Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fjpanag @xiaoxiang781216
Maybe the save() function should only set a new timer if g_settings.wrpend == 0?

I am obviously struggling a little here, sorry :(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm...been reading more....the save and/or dump functions need to become reentrant. Will take another look tomorrow, but still open to suggestions :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fjpanag @xiaoxiang781216
The more I think about this the more I wondering whether the "dump_cache" function should be removed completely?

The code as-is presumes a write to a block device (e.g. SD card) but that may not be what's wanted. In my case, I actually need to write the data to EEPROM, and only bytes that have changed, so that needs a separate and unrelated thread to handle it.

This code currently has the ability to signal other threads that c hange has occured. Is that not enough? Off load any async file saving away from this settings function?

I am also inclined to move away from a signal and move to a poll method instead?

What do you both think?

Otherwise, I think I should change it back to a draft PR - or even close it completely and forgot it? If it's not doing things "right" then I don't want to use it, nor will others, and it certainly isn't going to be merged of course.

@TimJTi TimJTi force-pushed the Add-settings-utility-and-example-app branch 2 times, most recently from 84da9fa to 0b25e5c Compare November 6, 2023 20:05
@fjpanag
Copy link
Contributor

fjpanag commented Nov 7, 2023

@TimJTi I would like to review this, if you don't mind, in case any change causes any issue already known to me.
I will try to check the app today, for proper usage of the API, and possibly tomorrow the actual settings code.

@xiaoxiang781216 How can I become a reviewer of the PR? Do I just leave comments inside of the commit page?

examples/settings/settings_main.c Outdated Show resolved Hide resolved
struct stat sbuf;

ASSERT(0);
if ((argc < 1) || *argv[1] == 0 || *(argv[1] + 1) == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ((argc < 1) || *argv[1] == 0 || *(argv[1] + 1) == 0)
if ((argc > 1) && (*argv[1] == 0 || *(argv[1] + 1) == 0))

I think your check here is wrong, for argc == 1, you access argv[1] which is an overflow.

goto print_help;
}

if (*argv[1] == '-')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (*argv[1] == '-')
if (argc > 1 && *argv[1] == '-')

Check first that the argument actually exists?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used in a variety of apps in the repo and seems to work though?

}
}

if (flag_present && argc < 2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this is an impossible condition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It checks that there aren't too many arguments. If the app is called as "settings -b -rubbish" it traps for that; even though it may be unnecessary. But it is strict and therefore OK I think?

{
printf("ERROR: Failed to mount tmpfs at %s: %d\n",
CONFIG_LIBC_TMPDIR, ret);
goto end;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will eventually return OK;. Maybe it's better to return an error in all these cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, it is the "return OK" at the end of the app that is wrong. That should be return ret

else
{
printf("INFO: a settings file was found and loaded\n");
ret = settings_get("v1", SETTING_STRING, readstr,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This call should always fail.

You try to access a setting without creating it first.
It must be created, even if a value already exists in the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it has been loaded from a file that has been found. Why do you have to create it (again)?

ret = settings_get("v1", SETTING_BOOL, &testval);
if (ret < 0)
{
printf("Deliberate fail: BOOL type requested not INT. Error:%d\n",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is not a failure.

The integer setting should be automatically converted to a boolean.
This should always succeed.

teststr = "I'm a string!";
printf("Changing an integer settings value (v1) to string:%s\n",
teststr);
ret = settings_create("v1", SETTING_STRING, teststr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should always fail. You are trying to create a setting that already exists!

If you want to change its type, you should be able to just settings_set() it to the new type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was rather left to guess what the functions did, and reverse engineer it all, so I did my best as a first pass :)

To me "create" is the first time the app wants to make use of a setting and "set" is to set the value and "get" is to get the value. If you try and "set" or "get" a value of the wrong type, should it not fail? But, yes, if you do want to change the type what do we do? I chose "create" meaning, in this case, re-create.

It does work, as I have interpreted it, but if its not in line with what you intended I apologise, and please clarify/explain :)

examples/settings/settings_main.c Outdated Show resolved Hide resolved
examples/settings/settings_main.c Outdated Show resolved Hide resolved
@TimJTi
Copy link
Contributor Author

TimJTi commented Nov 7, 2023

@TimJTi I would like to review this, if you don't mind, in case any change causes any issue already known to me. I will try to check the app today, for proper usage of the API, and possibly tomorrow the actual settings code.

I will be pushing a new commit with minor changes, and will wait for you to finish your much needed review before working on them. It is inevitable I have misunderstood the purpose or reasoning of things along the way :)

@TimJTi TimJTi force-pushed the Add-settings-utility-and-example-app branch 2 times, most recently from d618d48 to 95c3acf Compare November 7, 2023 17:09
@TimJTi TimJTi force-pushed the Add-settings-utility-and-example-app branch from 95c3acf to bf76cbd Compare November 9, 2023 11:25
@TimJTi TimJTi marked this pull request as draft November 12, 2023 13:44
@TimJTi
Copy link
Contributor Author

TimJTi commented Nov 12, 2023

Due to lack of interest. Will work on my own variant and maybe try and resubmit in the future.

@TimJTi TimJTi closed this Nov 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants