Skip to content

Implement viTerminate() for HiSLIP sessions (cross-thread I/O cancellation) #566

@jjgilles99

Description

@jjgilles99

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.

  1. A SCPI command like *WAI or a binary data query can block for seconds to minutes while the instrument completes an operation.
  2. The thread blocked in socket.recv_into() inside hislip.Instrument.receive() cannot be interrupted.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions