esp32 E.openFile stops working after multiple fs.readFile and fs.writeFile #7114
Replies: 1 comment
-
Posted at 2018-11-03 by @allObjects Could it be that it interferes with the upload of the code? ...because it is executing as part of that task. In first shot, just remove or comment the line with Posted at 2018-11-03 by mike_k I could take another screen shot of this happening using the upload button instead of copy and paste, but this snippet is really just an example of the problem happening in a much, much larger set of modules that I upload to the board. I was able to narrow down the problem to this section of my code, then made the most base-case example of the problem occurring (as shown in the screenshot) then I ensured it was the problem by running it via:
This issue happens in all three cases. Thank you for the quick reply btw! Posted at 2018-11-03 by Wilberforce As you are writing to a new file and not closing the last file - you are running out of buffers. If you close the file when you are done with it - or write the same file I don't think you would have an issue. Posted at 2018-11-04 by mike_k I am emphasizing that I am writing to a brand new file, I’ve tried all three possible ways of uploading, including uploading via console, uploading via the Upload button, as well as uploading via the Espruino command line tool, there are no other ways to upload. I’ve even wrapped the above code in an anonomyous function and executed, even with a setTimout to allow ANY other running scripts to load. I think @gfwilliams should give his opinion. If he thinks This is developer error, I will gladly continue to debug. I’ve reached a point where the only thing left for me to do is post on the forum, which I will always hold out as long as possible to do. but I’ve reached a point where i’ve narrowed down the problem and provided a example script that demonstrates the issue consistently. If you feel like this is still developer error, please let me know, and I will forgo the above conversation and move to a different library. Again, thank you for your help. Also, the first device I began tinkering with was an Espruino board because I wanted to support @gfwilliams ‘s work, because I know how hard he’s worked on this. Posted at 2018-11-04 by @allObjects @mike_k, I understand your frustration... first you give yourself the run-around, and then everyone else does it to you. As much I agree with that @gfwilliams has most of the insight, there are many others - when it comes to the non-Espruino boards and especially to espressif based boards - who did the ports and spend their time to push Espruino forward on those platforms. This was and is the case for ESP8266 boards, and is even more so for ESP32 boards, and is also mirrored in how @gfwilliams allocates support resources. So far, I did not use fs or File to that extend that I can answer all questions. I appreciate your thorough exploration of all paths before tapping into time of others. We all know about good and not so good 'forum citizens'...and the one being lazy. Trying and verifying all avenues upfront help debug an issue. Therefore, I think it has nothing to do with how the code gets uploaded or when and how its execution gets started. The last thing I could think of is that somehow resources are not released. This can happen due to Javascript being single threaded. I think though that you already took care of that by the I suggest code like that - in which I even try to reference the loop body function not by symbol reference but string reference - in two different ways: lines EDIT ...this code has a fundamental flaw - thanks @wilberforce to point that out in your following post. Therefore, take the code as sh0wn in my next post, post #8.
Since cutting the writings into separate JavaScript execution streaks with Btw, with Posted at 2018-11-04 by Wilberforce The issue here is this:
This is setting up 100 timeouts that will fire nealry at the same time. I think you are expecting them to queue up. If you get rid of the Posted at 2018-11-05 by @allObjects ...sorry, my bad... by tearing it apart I missed the part of calling the right thing from the right place. Here what I wanted to say:
Posted at 2018-11-11 by mike_k Thank you again for your attempt at mitigating the bug that I am facing. There are a few things I would like to cover regarding the code that you've provided, but it's important to note upfront that your changes still result in the same error that I am facing, so I would definitely call it a bug at this point. First off, your code has an unrecoverable syntax error on line 13: This was an easy fix, just had to find the syntax issue. Secondly, accessing a property on an object, regardless if it's global or not, does not need to be accessed via bracket notation just because it has a number at the end, so this may mislead someone to think this makes a difference stumbling upon this issue: Like you stated, writing anything like the following is not idiomatic javascript, and as you stated, the code involves a security risk if there is anything interpolated into the string in the first argument (because it uses eval under the hood), so I wouldn't do this either (but for the purposes of finding this fs related bug, I will leave it for now): Without further ado, Here is a screenshot of the resulting syntactically correct code randomly failing to write 14 / 100 files: I think the most frustrating part is that this issue occurs on both writes and reads (When reading, somethings undefined is returned even though using fs.statSync showns that the file exists and has length). Touching upon your other statement: I never stated that fs has a open or close function: I was stating that I had also attempted an alternative way of writing a file, specifically the functionality below that I did not post originally, because I had stated that "The same problems occur" intermittently:
Thank you again for all your help. I do not think there is any solution to this bug without looking under the hood, so I will file an issue on the github repo and then start digging. I have written error handling code that retries writing on error, but even then, sometimes it completely stops allowing me from writing to any file what-so-ever, until I execute a full reboot (which won't work in my control flow). So In the end, I think I'm going to have to look at the C code to see if there is anything suspicious occurring. Posted at 2018-11-12 by @allObjects The open/write/close pattern comment was made upon @wilberforce's post #4. Accessing a property of an object with property name as string or string variable in square bracket provides the ability to do it dynamic. No different ends, just different means (internally it goes a little bit a different path). In deed, nothing what so ever tried helps... Ic. Posted at 2018-11-12 by Wilberforce Hi, I suspected that memory was leaking so intially added a line to print free memory - as I suspected that this was the problem. the issue we have is if there is a failure - 0 is returned and we don't know which error occured or where... However in debugging - I found a work around.
Posted at 2018-11-12 by mike_k @wilberforce that is a solid work-around for now! I am able to execute write operations slightly more predictably now. But disappointingly, the ability to E.openFile still seems to lock up and return undefined after multiple read and write operations: If I can overcome this last lockup issue that would be excellent! Thank you again! Posted at 2018-11-12 by Wilberforce @mike_k As I believe there's only one file buffer you need to stick to either fs or fileopen calls. Every fileopen should be followed by a f.close() See here: https://www.espruino.com/File+IO Posted at 2018-11-12 by mike_k I don’t think I explained myself well enough in my last post above. My apologies. Every call I make to E.openFile is always followed by an f.close. This works consistently, until a call to E.openFile returns undefined, and i can no longer open and close files, respectively. The above example is explicitly showing the product of this - after running E.openFile, nothing is opened, i.e. undefined is returned (The 3rd-4th lines of the last image demonstrates the execution of the var f, and shows that undefined was assigned to it instead of a file object). Again, I open and close files sequentially, every time I open a file that actually returns a file object, I close right after. I hope that explains it better. As for the process.memory().free call, I am very grateful you found that work-around! I just hope I can find out why, after opening and closing a file multiple times, and making sure every file I open is indeed closed directly after, eventually causes E.openFile to no longer return anything. I think the first step in determining why the returned undefined value occurs is to explicitly throw an Out Of Memory error in the C code on the line of code that you’ve provided so it can much more easily be determined that we are simply out of memory vs some other underlying issue: http://microcosm.app/out/tGLJh Or, we should make E.openFile configurable in order to enable error throwing when we are out of memory. Again, this will allow developers to choose how to handle and discern whether or not a give api function isn’t working correctly because of lack of memory, or a different bug. I’d love to hear your thoughts on this, because it wouldn’t cause a lot (if any) of overhead and it gives the developer the choice of how they want to deal with Out Of Memory issues, whether it be via an undefined return value (like it currently does) or an actual thrown error. Thank you again @wilberforce!! Posted at 2018-11-12 by @gfwilliams Just tried it here on an official board, and on a Linux build with restricted vars and it works great.
Calling It looks like the filesystem stuff needs a flat array and is unable to find a large enough flat memory space for it... It is possible it's because of a memory leak... If it were something that wasn't unlocked you wouldn't expect the behaviour because GC wouldn't be able to free that, but if it were something that was referenced and not unreferenced then that could be it (but it's unlikely as it's very rare that anything outside of core touches references). OR... it might be because when you use the FAT filesystem on ESP32 the allocation units are 4k? That means each file ends up being quite big. I guess if there isn't much free RAM available then the data area might get too fragmented to allocate a 4k block of data after a while. I guess by the time GC actually runs, it's too late. Running GC manually will automatically re-order the free-list, which makes it significantly less likely that things get fragmented in the first place. Posted at 2018-11-12 by @gfwilliams How about running Posted at 2018-11-12 by @gfwilliams Just to add to this - while I don't seem to be able to reproduce on embedded, by dialling the available memory right down I can make it happen on the Linux build. It's Posted at 2018-11-12 by @gfwilliams Issue filed here: espruino/Espruino#1559 Actually running It should be easy enough to fix. Posted at 2018-11-12 by @gfwilliams If you take the latest travis builds they should stay working - although it'd be nice to figure out why the free list gets so out of order. Posted at 2018-11-12 by mike_k @gfwilliams you are awesome. I am unbelievably grateful that you jumped on this bug so quickly. I will try out the latest build later on tonight. Thank you again everyone! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Posted at 2018-11-02 by mike_k
First off, thank you to everyone who has contributed to the espruino project, I love it.
I'm running into an issue using an esp32 where, after multiple calls to fs.readFile / fs.writeFile, E.openFile starts returning undefined, and both fs.readFile / fs.writeFile start returning false. Below is an example of fs.writeFile returning false after only 10 writes:
I don't think there are any js functions exposed to inspect the situation that is causing this, but please let me know if there is. Also, I'm using a setTimeout above so I don't hit the watchdog timeout, basically simulating if I typed this into the espruino IDE 9 times. below is version information:
Also, I've tried variations of this with E.openFile thinking that I could circumvent the issue but the same problem occurs.
Thank you in advanced for the help!!
Beta Was this translation helpful? Give feedback.
All reactions