Marus780
Posts: 146
Joined: Sun Dec 11, 2022 2:22 pm

How to exit gracefully from the second Pico thread ?

Thu Feb 29, 2024 8:57 pm

Hi !
I made the following code in MicroPython to learn how threading works in Raspberry Pico.
When I press Ctrl+C, it indeed exits, but I receive an error in terminal window:
PROBLEM IN THONNY'S BACK-END: Exception while handling 'Run' (thonny.plugins.micropython.mp_back.ManagementError: Command output was not empty).
See Thonny's backend.log for more info.
You may need to press "Stop/Restart" or hard-reset your MicroPython device and try again.
Process ended with exit code 1.
This type of error is triggered when the main thread finishes but the second is still running. First time I forgot to exit the 'while' loop and then I could no longer use the Pico with Thonny until I nuked the Pico flash and write the firmware again. Now it exits, but it still throw that error. And I even inserted a 1s delay after I signaled the thread to terminate... In Pico we don't have a way to wait for a thread to finish (something like thread.join()) ?
I also don't get the message "New thread is terminating gracefully."

Code: Select all

import _thread
import time

terminate = False

def my_thread(EndFlag):
  print("New thread is running...")
  while not EndFlag:
    time.sleep(0.2) 
  print("New thread is terminating gracefully.")
    
_thread.start_new_thread(my_thread, (terminate,))

try:
  while True:
    time.sleep(2) 
except KeyboardInterrupt:
  terminate = True
  time.sleep(1)
  print("Main thread terminated gracefully.")



hippy
Posts: 16128
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: How to exit gracefully from the second Pico thread ?

Fri Mar 01, 2024 1:05 am

I think it's because you pass the terminate flag in as a parameter variable, so it's set once and that's it. You need something like this where it's global, can be changed live in the main code and those changes get seen as they happen within the thread...

Code: Select all

running = True

def my_thread():
  while running:
    ...
  print("New thread is terminating gracefully.")
    
_thread.start_new_thread(my_thread, (,))

try:
  while whatever:
     ...
except KeyboardInterrupt:
  pass
finally:
  running = False

Marus780
Posts: 146
Joined: Sun Dec 11, 2022 2:22 pm

Re: How to exit gracefully from the second Pico thread ?

Fri Mar 01, 2024 1:33 pm

I do like this and it works ! :) It seems that in the first example the EndFlag was passed by value, not by reference...
By the way, is there a method to know when a thread is terminated ? Or wait for it to finish ? In the Pico/MicroPython context...

Code: Select all

import _thread
import time

terminate = False

def my_thread():
  global terminate
  print("New thread is running...")
  while not terminate:
    time.sleep(0.2) 
  print("New thread is terminating gracefully.")
    
_thread.start_new_thread(my_thread, ())

try:
  while True:
    time.sleep(2) 
except KeyboardInterrupt:
  terminate = True
  time.sleep(0.3)
  print("Main thread terminated gracefully.")


hippy
Posts: 16128
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: How to exit gracefully from the second Pico thread ?

Fri Mar 01, 2024 1:41 pm

To tell when a thread has terminated I would use a second global variable ...

Code: Select all

running  = True
finished = False

def my_thread():
  global finished
  while running:
    ...
  print("New thread is terminating gracefully.")
  finished = True
    
_thread.start_new_thread(my_thread, (,))

try:
  while whatever:
     ...
except KeyboardInterrupt:
  pass
finally:
  running = False
while not finished:
  pass
print("Thread has finished and so will we")

jkozniewski
Posts: 1
Joined: Sun Mar 17, 2024 1:49 pm

Re: How to exit gracefully from the second Pico thread ?

Sun Mar 17, 2024 2:01 pm

Hi @Marus780 - are you 100% sure it works every time ?

I've used exactly same code that you've posted and still after few uploads the pico gets unresponsive and needs to get disconnected manually.
I;m using latest firmware (MicroPython v1.22.2 on 2024-02-22; Raspberry Pi Pico W with RP2040) though I've tried to use earlier builds and even nightly ones but it always crashes at some point... Running Thonny on Mac OS Sonoma, M3.

I kind of just started playing with _threads on pico w and understand that _threads module is experimental and there are major caveats, but I'm surprised that such basic thing as not being able tu use REPL consistently thus effectively work on code via uploading it a lot trough VS Code or Thonny is so broken...

Is it really _that_ bad, or I'm missing something - seems there are people using threads on pico w, just struggling with some more intricate bugs than the whole board becoming unresponsive after few code uploads / soft restarts...

hippy
Posts: 16128
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: How to exit gracefully from the second Pico thread ?

Sun Mar 17, 2024 4:46 pm

jkozniewski wrote:
Sun Mar 17, 2024 2:01 pm
I understand that _threads module is experimental and there are major caveats, but I'm surprised that such basic thing as not being able tu use REPL consistently thus effectively
That's probably one of those major caveats :)
jkozniewski wrote:
Sun Mar 17, 2024 2:01 pm
Is it really _that_ bad
It's hard to quantify. Some people have no problems, other people do, some more than others.

Things are a whole lot better than they used to be with '_thread' but there do seem to be some issues remaining, issues which may be more noticeable or problematic when developing code and returning to the REPL than running finished code on a Pico. What's tolerable and acceptable is in the eye of the beholder.

Thus the warnings and cautions. Pragmatically you either accept the risk of problems which may come with using '_thread' or don't use it. You can provide feedback on the issue to the MicroPython team, even sponsor research into problems and fixes -

https://github.com/orgs/micropython/discussions

Return to “MicroPython”