-
Notifications
You must be signed in to change notification settings - Fork 575
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
Conversation
I have no idea why this is failing CI? HELP! |
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? |
6db40dd
to
31d654a
Compare
how about system/ folder? Many utility libraries put there. |
235000c
to
c725bc1
Compare
@xiaoxiang781216 It still fails CI - I HAVE NO IDEA!!!!!!!!!!! |
865a2d6
to
e1813e4
Compare
@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:
You're probably using |
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. |
e1813e4
to
9a8b964
Compare
@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 May be time for me to jump ship to a different edit/build/debug workflow completely!!!!!!!!!! |
In my case it was just installing
If this doesn't work, then probably the packages installed with pip (usually |
Thank you - installed and working! |
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); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
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:
- Calls to the save function are obviously asynchronous
- Each call to the save function sets a a new timer
- 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?
There was a problem hiding this comment.
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 :(
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
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.
84da9fa
to
0b25e5c
Compare
@TimJTi I would like to review this, if you don't mind, in case any change causes any issue already known to me. @xiaoxiang781216 How can I become a reviewer of the PR? Do I just leave comments inside of the commit page? |
struct stat sbuf; | ||
|
||
ASSERT(0); | ||
if ((argc < 1) || *argv[1] == 0 || *(argv[1] + 1) == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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] == '-') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (*argv[1] == '-') | |
if (argc > 1 && *argv[1] == '-') |
Check first that the argument actually exists?
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 :)
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 :) |
d618d48
to
95c3acf
Compare
95c3acf
to
bf76cbd
Compare
Due to lack of interest. Will work on my own variant and maybe try and resubmit in the future. |
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.