Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    Main thread blocks auxiliary threads (_thread module)

    Scheduled Pinned Locked Moved Issues & Bugs
    8 Posts 5 Posters 324 Views 5 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D Offline
      d.alvrzx
      last edited by d.alvrzx

      Dear all:

      With the new Pycom firmware (v1.20.2.rc6), the main thread appears to block auxiliary threads.

      Issue description:

      To repeat this issue, run the following code with a LoPy4 with Pycom's v1.20.2.rc6 firmware:

      import pycom
      import time
      import _thread
      
      pycom.heartbeat(False)
      
      def blinkLoop():
          while True:
              pycom.rgbled(0xff0000)
              time.sleep(0.5)
              pycom.rgbled(0x00ff00)
              time.sleep(0.5)
      
      blink_process = _thread.start_new_thread(blinkLoop, ())
      
      x = 0
      
      while True:
          #time.sleep(0.1)
          x = x + 1
      

      When time.sleep(0.1) is commented out, the blinkLoop thread does not execute (no blinking is observed in the LED). If you add the 0.1 second delay (uncomment that line), the blinkLoop thread executes without any (discernible) problems.

      When did this problem come up?

      In v1.20.0.rc13 of Pycom's firmware, the 0.1 second delay is not necessary in order for the blinkLoop thread to execute correctly. When updating to v1.20.2.rc6, the delay is necessary. This is an undesirable behaviour for my application.

      These are the 2 firmwares mentioned above:

      (sysname='LoPy4', nodename='LoPy4', release='1.20.0.rc13', version='v1.9.4-94bb382 on 2019-08-22', machine='LoPy4 with ESP32', lorawan='1.0.2', sigfox='1.0.1')
      

      and

      (sysname='LoPy4', nodename='LoPy4', release='1.20.2.rc6', version='v1.11-01f49f7 on 2020-02-28', machine='LoPy4 with ESP32', lorawan='1.0.2', sigfox='1.0.1', pybytes='1.3.1')
      

      Why does this happen? Has something been changed in the _thread module during the v1.20.2.rc6 firmware release? Or maybe in the change to micropython v1.11? Any ideas or help is appreciated.

      Thank you in advance.

      Best regards,

      Dan

      robert-hhR 1 Reply Last reply Reply Quote 0
      • P Offline
        peterp
        last edited by

        Hey Dan,

        I've noticed as well. It is a change in behaviour indeed. Unfortunately, determining the root cause is not trivial though. I suspect it is some change inside IDF, maybe FreeRTOS inside the IDF.

        Can you elaborate why a small sleep in the main thread is undesirable for your application?

        D 1 Reply Last reply Reply Quote 1
        • robert-hhR Offline
          robert-hh @d.alvrzx
          last edited by

          @d-alvrzx The observation that busy loops block other activities is present since long, even before v1.20.0. The cure is typically to add machine.idle() or a short sleep into the loop. In your example, machine.idle() does not work, and the shortest possible sleep time seems to be 1 ms or 1001µs.

          D 1 Reply Last reply Reply Quote 1
          • D Offline
            d.alvrzx @peterp
            last edited by

            @peterp Hello Peter. Thank you for your prompt response. Regarding your question, it is not "undesirable" as such, but I did not like the idea of having to add a delay (even if it was 1 ms), when in the past my code used to work without it. But I understand it seems to be necessary, and so I can add it without problem (although it does make me feel a bit uncomfortable, haha).

            One last question I would have would be: Do you know of any other issues that might arise regarding threads in this new firmware version? Or is it realistic to say that I can just add this 1 ms delay and then forget about it? i.e. Would I encounter no other issues in the future? I understand this is a very, very broad question, but I'm just looking for any info/experience you might have on this.

            Thanks!

            P 1 Reply Last reply Reply Quote 0
            • P Offline
              peterp @d.alvrzx
              last edited by

              @d-alvrzx said in Main thread blocks auxiliary threads (_thread module):

              @peterp Hello Peter. Thank you for your prompt response. Regarding your question, it is not "undesirable" as such, but I did not like the idea of having to add a delay (even if it was 1 ms), when in the past my code used to work without it. But I understand it seems to be necessary, and so I can add it without problem (although it does make me feel a bit uncomfortable, haha).

              Great! (me too ;) )

              One last question I would have would be: Do you know of any other issues that might arise regarding threads in this new firmware version? Or is it realistic to say that I can just add this 1 ms delay and then forget about it? i.e. Would I encounter no other issues in the future? I understand this is a very, very broad question, but I'm just looking for any info/experience you might have on this.

              Thanks!

              A very broad question indeed :) To the best of my knowledge there are no other changes that you need to be aware of. I expect threads to "just work", as long as the main thread "yields" by sleeping a little at some point.

              1 Reply Last reply Reply Quote 1
              • D Offline
                d.alvrzx @robert-hh
                last edited by

                @robert-hh Thank you very much for your detailed response. I have in fact tried the 1 ms delay within my actual code (the example I posted was just a short piece of code to replicate the problem) and it in fact works. So thanks for that. Maybe you could give me you insight into the question I posed to @peterp, which was:

                @d-alvrzx said in Main thread blocks auxiliary threads (_thread module):

                One last question I would have would be: Do you know of any other issues that might arise regarding threads in this new firmware version? Or is it realistic to say that I can just add this 1 ms delay and then forget about it? i.e. Would I encounter no other issues in the future? I understand this is a very, very broad question, but I'm just looking for any info/experience you might have on this.

                Best wishes,

                Dan

                1 Reply Last reply Reply Quote 0
                • A Offline
                  alvaroav
                  last edited by alvaroav

                  Dear all,

                  Yesterday I updated the firmware of some units, in order to follow the supported firmware versions (previously I used the v1.20.0r3 legacy and I went directly to the latest v1.20.2r4 pybytes).
                  Then I debugged the code I have for the wipys, and everthing works except the _thread running in paralell to the main, in order to listen UDP sockets for start/stop data transmission. I was looking for info related to the changes and I found this post, which shows exactly the problem I had.
                  I have also applied to proposed solution, and this makes my code operational again, BUT I lost 10% of speed performance, since I have to place a time.sleep_ms(1) at the end of the while(True) of the main loop.
                  Does someone look for a better solution, or have clear idea of what was changed at _thread implementation?
                  Thanks to all!

                  1 Reply Last reply Reply Quote 0
                  • Pablo WoolvettP Offline
                    Pablo Woolvett
                    last edited by Pablo Woolvett

                    Hi all,

                    We did not like the idea of sleeping, so we implemented an alternative workaround using two locks, which we believe it to be more robust.

                    import time
                    import _thread
                    
                    class Thread:
                    
                        def init(self, target):
                            self.result = None
                            self.target = target
                            self.lock = _thread.allocate_lock()
                            self.aux_lock = _thread.allocate_lock()
                    
                        def real_call(self):
                            with self.lock:
                                self.aux_lock.release()
                                self.result = self.target()
                    
                        def call(self):
                            self.aux_lock.acquire()
                            _thread.start_new_thread(self.real_call, ())
                            with self.aux_lock:
                                pass
                    
                        def join(self):
                            with self.lock:
                                pass
                    
                    def demo():
                        print("Starting")
                        time.sleep(10)
                        print("Ensing")
                        return 42
                    
                    
                    def main():
                    
                        t = Thread(target = demo)
                        t()
                        t.join()
                        print("Result: " + str(t.result))
                    
                    if name == "main":
                        main()
                    
                    
                    1 Reply Last reply Reply Quote 1

                    Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                    Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                    With your input, this post could be even better 💗

                    Register Login
                    • 1 / 1
                    • First post
                      Last post

                    Pycom on Twitter

                    Pycom