Skip to content
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

Iterator zombie won't die :) #13

Closed
cefn opened this issue Feb 22, 2013 · 3 comments
Closed

Iterator zombie won't die :) #13

cefn opened this issue Feb 22, 2013 · 3 comments

Comments

@cefn
Copy link

cefn commented Feb 22, 2013

The Iterator thread doesn't die gracefully on KeyboardInterrupt or SystemExit, or when the Main thread completes.

Additionally, the function _Thread__stop() which does indeed kill the Iterator doesn't appear to be broken out to a nice function call, like Iterator.stop() as seems to be suggested within the Mockup implementation.

I propose setting the Iterator thread's isDaemon() flag to True in the Iterator constructor

        self.setDaemon(True)

If the developer chooses to call Iterator run() in the main thread (preventing the python interpreter from returning) they may need code like the following so it can be killed when foregrounded...

            except(KeyboardInterrupt, SystemExit), e:
                sys.exit()

...and a simple extra method to map the stop function to Thread's stopping function could be nice...

def stop(self):
    self._Thread__stop()
@tino
Copy link
Owner

tino commented Mar 20, 2013

Hi, I think I've experienced this as well before, but I am not really familiar with all ins and outs of threads. Could you make a pull request out of this?

@NeoPolus
Copy link

Hi, this bug is due to Board.exit() never getting called automatically from Board.__del__() as long as there is a Iterator thread running.
This happens because the Iterator thread keeps a -circular- reference to the Board! So if you try to stop Python (keyboard interruption or any exception...) the main thread dies but Python does not call Board.__del__() yet and instead keeps waiting for the Iterator thread to stop... which never happens.
So, unless you manually call Board.exit() under any situation ("try:... finally: board.exit()") is highly probable that your Iterator will become a zombie.

I created a new pull request (#45) with some commits that fix this problem by implementing the support for the Python "with" statement, so you can do something like this:

>> from pyfirmata import Arduino, util
>> board = Arduino('/dev/tty...')
>> with board:
>>     board.analog[0].enable_reporting()
>>     board.analog[0].read()

and it will take care of creating the Iterator thread at the beginning of the with block and stopping it (automatically calling board.exit()) at the end of the block even when an exception happens. So it would be a shorter (and cooler ;) ) equivalent to:

>> from pyfirmata import Arduino, util
>> board = Arduino('/dev/tty...')
>> it = util.Iterator(board)
>> it.start()
>> try:
>>     board.analog[0].enable_reporting()
>>     board.analog[0].read()
>> finally:
>>     board.exit()
>>     it = None

I hope @tino likes the pull request and merges it soon :)

@tino
Copy link
Owner

tino commented Oct 29, 2016

Fix with #44

@tino tino closed this as completed Oct 29, 2016
dschlimovich added a commit to dschlimovich/proyectofinal that referenced this issue Jul 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants