Pipe error on reconnect to USB instrument
Ryan-Draves opened this issue · 5 comments
When opening a resource to a USB instrument after a resource to the same instrument has been closed, an [Errno 32] Pipe error
may appear. The re-opening doesn't need to happen in the same process; the error will persist until the USB connection is reset by unplugging the cable or until the instrument is power cycled. I have been able to consistently reproduce this on some machines with a Rigol DP832, but other machines don't encounter this issue, even with the same pyvisa-py
version and, to my knowledge, system installations.
I searched for versions affected by this and isolated it to 0.6.2
and the #352 and related changes.
To Reproduce
Steps to reproduce the behavior:
import pyvisa
rm = pyvisa.ResourceManager()
inst = rm.open_resource('some_usb_address')
inst.query('*IDN?') # make sure communication works
inst.close() # clean up resource
rm_2 = pyvisa.ResourceManager()
inst_2 = rm.open_resource('some_usb_address')
inst_2.query('*IDN?') # USBError: [Errno 32] Pipe error
Output of pyvisa-info
Machine Details:
Platform ID: Linux-5.14.0-1059-oem-x86_64-with-glibc2.29
Processor: x86_64
Python:
Implementation: CPython
Executable: /usr/bin/python3.8
Version: 3.8.10
Compiler: GCC 9.4.0
Bits: 64bit
Build: Mar 13 2023 10:26:41 (#default)
Unicode: UCS4
PyVISA Version: 1.13.0
Backends:
ivi:
Version: 1.13.0 (bundled with PyVISA)
Binary library: Not found
py:
Version: 0.6.3
ASRL INSTR: Available via PySerial (3.5)
USB INSTR: Available via PyUSB (1.2.1). Backend: libusb1
USB RAW: Available via PyUSB (1.2.1). Backend: libusb1
TCPIP INSTR: Available
Resource discovery:
- VXI-11: ok
- hislip: disabled (zeroconf not installed)
VICP INSTR:
Please install PyVICP to use this resource type.
TCPIP SOCKET: Available
GPIB INSTR:
Please install linux-gpib (Linux) or gpib-ctypes (Windows, Linux) to use this resource type. Note that installing gpib-ctypes will give you access to a broader range of funcionality.
No module named 'gpib'
sim:
Version: 0.5.1
Spec version: 1.1
This sounds quite mysterious. But it seems always so with USB issues.
If you figure out what differs between your machines, it would be great. On the machine on which things work, does it also work before 0.6.2 ?
Yeah, no issues of this type before 0.6.2
across any machines I've tested with. I can get back to you on Monday to run pyvisa-info
on some different machines and see if they have different outputs.
Could you also post the full traceback just to help understand where in the stack the error occurs ?
The original post had a pyvisa-info
output from my laptop, which is working on 0.6.3
(pardon the confusion). I ran pyvisa-info
from a machine with the issue, the only difference being the machine details section:
Machine Details:
Platform ID: Linux-5.15.0-71-generic-x86_64-with-glibc2.29
Processor: x86_64
Here's the requested traceback. I confirmed the same commands work if I downgrade to 0.6.1
:
In [7]: rm = pyvisa.ResourceManager()
In [8]: inst = rm.open_resource('USB0::6833::3601::DP8B242902278::0::INSTR')
In [9]: inst.query('*IDN?')
Out[9]: 'RIGOL TECHNOLOGIES,DP832A,DP8B242902278,00.01.16\n'
In [10]: inst.close()
In [11]: rm = pyvisa.ResourceManager()
In [12]: inst = rm.open_resource('USB0::6833::3601::DP8B242902278::0::INSTR')
In [13]: inst.query('*IDN?')
---------------------------------------------------------------------------
USBError Traceback (most recent call last)
~/.local/lib/python3.8/site-packages/pyvisa_py/protocols/usbtmc.py in write(self, data)
276 try:
--> 277 return self.usb_send_ep.write(data)
278 except usb.core.USBError as e:
~/.local/lib/python3.8/site-packages/usb/core.py in write(self, data, timeout)
407 """
--> 408 return self.device.write(self, data, timeout)
409
~/.local/lib/python3.8/site-packages/usb/core.py in write(self, endpoint, data, timeout)
988
--> 989 return fn(
990 self._ctx.handle,
~/.local/lib/python3.8/site-packages/usb/backend/libusb1.py in bulk_write(self, dev_handle, ep, intf, data, timeout)
836 def bulk_write(self, dev_handle, ep, intf, data, timeout):
--> 837 return self.__write(self.lib.libusb_bulk_transfer,
838 dev_handle,
~/.local/lib/python3.8/site-packages/usb/backend/libusb1.py in __write(self, fn, dev_handle, ep, intf, data, timeout)
937 if not (transferred.value and retval == LIBUSB_ERROR_TIMEOUT):
--> 938 _check(retval)
939
~/.local/lib/python3.8/site-packages/usb/backend/libusb1.py in _check(ret)
603 else:
--> 604 raise USBError(_strerror(ret), ret, _libusb_errno[ret])
605
USBError: [Errno 32] Pipe error
During handling of the above exception, another exception occurred:
ValueError Traceback (most recent call last)
<ipython-input-13-550ce4f5045a> in <cell line: 1>()
----> 1 inst.query('*IDN?')
~/.local/lib/python3.8/site-packages/pyvisa/resources/messagebased.py in query(self, message, delay)
640
641 """
--> 642 self.write(message)
643
644 delay = self.query_delay if delay is None else delay
~/.local/lib/python3.8/site-packages/pyvisa/resources/messagebased.py in write(self, message, termination, encoding)
195 message += term
196
--> 197 count = self.write_raw(message.encode(enco))
198
199 return count
~/.local/lib/python3.8/site-packages/pyvisa/resources/messagebased.py in write_raw(self, message)
155
156 """
--> 157 return self.visalib.write(self.session, message)[0]
158
159 def write(
~/.local/lib/python3.8/site-packages/pyvisa_py/highlevel.py in write(self, session, data)
541 # from the session handle, dispatch to the write method of the session object.
542 try:
--> 543 written, status_code = self.sessions[session].write(data)
544 except KeyError:
545 return 0, self.handle_return_value(session, StatusCode.error_invalid_object)
~/.local/lib/python3.8/site-packages/pyvisa_py/usb.py in write(self, data)
177 send_end, _ = self.get_attribute(ResourceAttribute.send_end_enabled)
178
--> 179 count = self.interface.write(data)
180
181 return count, StatusCode.success
~/.local/lib/python3.8/site-packages/pyvisa_py/protocols/usbtmc.py in write(self, data)
451 data = BulkOutMessage.build_array(self._btag, eom, data[begin:end])
452
--> 453 bytes_sent += raw_write(data)
454
455 return size
~/.local/lib/python3.8/site-packages/pyvisa_py/protocols/usbtmc.py in write(self, data)
277 return self.usb_send_ep.write(data)
278 except usb.core.USBError as e:
--> 279 raise ValueError(str(e))
280
281 def read(self, size):
ValueError: [Errno 32] Pipe error
I'm experiencing the same issue on my Rigol DS1102Z-E and have determined the root cause: USB autosuspend.
# cat /sys/module/usbcore/parameters/autosuspend
# 2
Which means devices are autosuspended on a two second timeout. For whatever reason this only happens after the device has been opened/used once, so that means you can access the device once and then repeatedly until you leave it untouched for two seconds.
(Note the pipe error originates from the USB layer (URB status: Broken pipe (-EPIPE)
).)
Disabling autosuspend as a workaround fixes it for me:
# echo -1 > /sys/module/usbcore/parameters/autosuspend
More importantly, reverting #352 also fixes the issue - ie. ensuring SET CONFIGURATION
is executed after resume from suspend - at least on Rigol devices (?).
I don't really know USB, so perhaps someone else is able to tell whether this is a pyvisa, pyusb or Rigol bug?