-
-
Notifications
You must be signed in to change notification settings - Fork 134
Description
pyvisa-py has no implementation of viTerminate() — the VisaLibraryBase.terminate() method raises NotImplementedError. For HiSLIP sessions, this means there is no way to cancel a pending I/O operation from another thread.
- A SCPI command like
*WAIor a binary data query can block for seconds to minutes while the instrument completes an operation. - The thread blocked in
socket.recv_into()insidehislip.Instrument.receive()cannot be interrupted. - The only workaround is
socket.shutdown(SHUT_RDWR)from another thread.
The VISA spec defines viTerminate() to handle exactly this case: cancel a pending synchronous operation so it returns VI_ERROR_ABORT, without destroying the session.
Proposed solution
Implement viTerminate() for TCPIPInstrHiSLIP using a cancellable socket wrapper.
CancellableSocket
Wrap the HiSLIP sync socket so that recv_into() uses select() to watch both the
data socket and a cancel pipe (socket.socketpair()). When cancel() is called from
another thread, the blocked select() returns immediately.
class CancellableSocket:
def __init__(self, sock):
self._sock = sock
self._cancel_r, self._cancel_w = socket.socketpair()
...
def recv_into(self, buffer, nbytes=0, flags=0):
readable, _, _ = select.select(
[self._sock, self._cancel_r], [], [], timeout
)
if self._cancel_r in readable:
self._drain_cancel()
raise HiSLIPInterruptedError(0)
return self._sock.recv_into(buffer, nbytes, flags)
def cancel(self):
self._cancel_w.send(b"\x00")This is a drop-in replacement — all existing code that calls sock.recv_into() (including receive_exact_into, RxHeader, receive_flush) gets cancellation support transparently.