vpelletier / python-libusb1

Python ctype-based wrapper around libusb1
GNU Lesser General Public License v2.1
168 stars 65 forks source link

RuntimeError when exiting the hotplug.py example #31

Closed hetsch closed 6 years ago

hetsch commented 6 years ago

Hi,

first thank you for this library and your hard work! I tried to execute the hotplug.py from the examples directory. Works fine so far until I exit the program with ^C. This is the error that I get:

bash-3.2$ python libusb.py 
Registering hotplug callback...
Device arrived: Bus 250 Device 009: ID 05ac:821a
Device arrived: Bus 250 Device 006: ID 046d:c526
Device arrived: Bus 253 Device 004: ID 05ac:020c
Device arrived: Bus 250 Device 005: ID 05ac:0253
Device arrived: Bus 250 Device 004: ID 0a5c:4500
Device arrived: Bus 250 Device 003: ID 1a40:0101
Device arrived: Bus 253 Device 003: ID 05ac:1003
Device arrived: Bus 253 Device 002: ID 05ac:8242
Device arrived: Bus 250 Device 002: ID 0424:2513
Device arrived: Bus 250 Device 001: ID 05ac:8509
Device arrived: Bus 253 Device 001: ID 0424:2513
Callback registered. Monitoring events, ^C to exit
^CExiting
Traceback (most recent call last):
  File "libusb.py", line 126, in <module>
    main()
  File "libusb.py", line 123, in main
    print('Exiting')
  File "/Volumes/Data/Users/xxx/.local/share/virtualenvs/python-u35SbPCX/lib/python3.6/site-packages/usb1/__init__.py", line 2156, in __exit__
    self.close()
  File "/Volumes/Data/Users/xxx/.local/share/virtualenvs/python-u35SbPCX/lib/python3.6/site-packages/usb1/__init__.py", line 2189, in close
    self._exit()
  File "/Volumes/Data/Users/hetsch/.local/share/virtualenvs/python-u35SbPCX/lib/python3.6/site-packages/usb1/__init__.py", line 2197, in _exit
    for handle in self.__hotplug_callback_dict.keys():
RuntimeError: dictionary changed size during iteration

I haven't attached any devices, just started and and then imediately exited the program without any other interaction.

My environment:

Python 3.6.3 (default, Oct  4 2017, 06:09:05) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin

libusb1 1.6.4 (latest pypi version)

brew info libusb
libusb: stable 1.0.21 (bottled), HEAD
Library for USB device access
http://libusb.info
/usr/local/Cellar/libusb/1.0.21 (29 files, 510.5KB) *
Poured from bottle on 2017-09-13 at 17:18:48
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/libusb.rb
vpelletier commented 6 years ago

Thanks for the report.

for handle in self.__hotplug_callback_dict.keys():

RuntimeError: dictionary changed size during iteration

Woops, looks like I did not tell setup.py to run 2to3 when running on python3.

Should be fixed in 3926ad473f0c7e660520a7daa4d2b1254dacbe74 .

Now, why did travis not catch this ?

hetsch commented 6 years ago

@vpelletier Thank you for fixing this issue, work perfect now. I'm sorry but I'm not really experienced with travis but if I have some spare time, I will try my best and have a look at the travis part ...

vpelletier commented 6 years ago

Thanks a lot for reporting that fix works.

Sorry about the travis bit, this was not an actual question but rather me being puzzled out loud.

hetsch commented 6 years ago

@vpelletier There seems to be another issue with python3 and the hotplug_advanced.py example. 2to3 outputs the following diff:

--- hotplug_advanced.py (original)
+++ hotplug_advanced.py (refactored)
@@ -18,7 +18,7 @@
 Advanced hotplug examples.
 Presents ways of integrating hotplug into your userland USB driver.
 """
-from __future__ import print_function
+
 import select
 import sys
 import usb1
@@ -58,12 +58,12 @@
         for fd_list, happened_flag in zip(
                 select.select(*([[
                     fd
-                    for fd, events in self._fd_dict.iteritems() if events & flag
+                    for fd, events in self._fd_dict.items() if events & flag
                 ] for flag in flag_list] + [timeout])),
                 flag_list,
             ):
             result[fd] = result.get(fd, 0) | happened_flag
-        return result.items()
+        return list(result.items())
 # (end of demonstration helpers)

 class AwesomeDevice(object):
@@ -227,7 +227,7 @@
     )
     try:
         mode()
-    except NoHotplugSupport, exc:
+    except NoHotplugSupport as exc:
         print(exc.value)
         sys.exit(1)
     except (KeyboardInterrupt, SystemExit):

Applying these changes leads, at least on my platform, to the following error:

Traceback (most recent call last):
  File "hotplug_advanced.py", line 237, in <module>
    main()
  File "hotplug_advanced.py", line 229, in main
    mode()
  File "hotplug_advanced.py", line 210, in eventloop
    poller.poll()
  File "/xxx/lib/python3.6/site-packages/usb1/__init__.py", line 1096, in poll
    event_list = self.__poller.poll(usb_timeout)
  File "hotplug_advanced.py", line 65, in poll
    result[fd] = result.get(fd, 0) | happened_flag
NameError: name 'fd' is not defined