How to exit a thread
Noob question. What is the appropriate way of closing a thread?
_threadprovides a function called
exit()but I'm not sure how it could be of use. There is no documentation on it.
See this example:
import _thread import time import gc gc.enable() def thr(delay, id): print("id: %r, thr_id: %r" % (id, _thread.get_ident())) _thread.exit() i = 0 while True: time.sleep(1) print("Current thread is: %r" % (_thread.get_ident())) _thread.start_new_thread(thr, (0 , i)) i += 1
It will lead to a memory allocation error after 3 threads has been started, while ideally, it should never lead to a memory allocation error. How can I close a thread properly?
I can confirm this issue has been fixed in
1.2.2.b1. AMAZING! Kudos.
Thanks for the clarification, although I knew about
collect()and I was doing it in another version which had no effect whatsoever, just posted a variation of my test case.
I'm glad it is solved now and from what I got from posting in this forum, (fortunately for us) pycom doesn't need us to peer pressure on the issues, they actually read and act on every bug report, which is amazing!
@mohpor: Yes, I agree. I just wanted to confirm you observation. Sometimes it helps, if more people complain.
With the new release of the firmware, the issue is gone. It is still advisable, to make a manual gc.collect(), otherwise the free memory will continuously go down, until eventually an automatic gc.collect is enforced. See log below, w/o that gc.collect() call in the loop.
>>> import thread 41392 Current thread is: 1073547588 id: 0, thr_id: 1073506400 41232 Current thread is: 1073547588 id: 1, thr_id: 1073506400 41072 Current thread is: 1073547588 id: 2, thr_id: 1073506400 40912 Current thread is: 1073547588 id: 3, thr_id: 1073506768 40752 .....
With a gc.collect() call in the loop, the free memory settles at a certain amount.
@robert-hh That's my original assessment. As you can see, each new Thread requires 8816 bytes and when the memory gets depleted, no more threads can be started.
@abilio Thanks for the reply. If I could make a proper suggestion for the documentation, that would be the dire need of explaining memory management and most especially the implication of things like multi-threading have on memory. As I can see, there is very limited memory available on board which needs very careful management of it. I'm not even sure how I can use such limited memory in my application, but I hope when everything is done and ready, you'd optimize memory and we will have much more memory at hand.
Hello @robert-hh, we were already working in a solution for problems like the one you detected. If everything goes well, is planned to be released this evening or tomorrow. As usual, thanks a lot for all the feedback you give.
Just for interest, I took the sample above and added gc.collect() and a print statement. The code now looks like:
import _thread import time import gc def thr(delay, id): print("id: %r, thr_id: %r" % (id, _thread.get_ident())) _thread.exit() i = 0 while True: time.sleep(1) gc.collect() print(gc.mem_free()) print("Current thread is: %r" % (_thread.get_ident())) _thread.start_new_thread(thr, (0 , i)) i += 1
It fails at the 3rd attempt, getting now new buffer for the thread. It looks like the memory is not released, even when after 1 second the new started thread should have terminated and it's memory not needed any more. Out put below:
MicroPython v1.8.6-299-gf7f29f4 on 2017-01-07; LoPy with ESP32 Type "help()" for more information. >>> import thread 25952 Current thread is: 1073524960 id: 0, thr_id: 1073497424 17248 Current thread is: 1073524960 id: 1, thr_id: 1073505616 8608 Current thread is: 1073524960 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "thread.py", line 15, in <module> MemoryError: memory allocation failed, allocating 8192 bytes
@mohpor, when the method that handles the new thread finishes execution, the thread is automatically deleted, so the proper ay would be not calling anything at all.
Thanks for the feedback on the lack of threading documentation. Threading is a relatively new feature in micropython, and there is still no documentation available. We will provide one in an upcoming release of the docs.