-
Notifications
You must be signed in to change notification settings - Fork 12
Description
Summary
The zmq.poll() function in pbdZMQ expects its first argument to be a vector of socket pointers, but when a single socket pointer is passed (which is a common use case), it produces a cryptic error message that doesn't indicate the actual problem. The function should validate its arguments and provide a clear error message.
Expected Behavior
When calling zmq.poll(socket, ...) with a single socket pointer, the function should either:
- Accept the single socket and treat it as a vector of length 1, OR
- Provide a clear error message indicating that a vector is required
Actual Behavior
The function produces a cryptic error:
Error in LENGTH() or similar applied to externalptr object
This error message doesn't indicate that the issue is with the argument type to zmq.poll().
Reproducible Example
library(pbdZMQ)
# Create context and socket
context <- zmq.ctx.new()
socket <- zmq.socket(context, ZMQ.ST()$REQ)
# Connect to a dummy endpoint (doesn't need to be real for this error)
zmq.connect(socket, "tcp://localhost:5555")
# Send a message
zmq.send(socket, "Hello")
# This produces the cryptic error:
# Error in LENGTH() or similar applied to externalptr object
poll_result <- zmq.poll(socket, ZMQ.PO()$POLLIN, timeout = 1000)
# Clean up
zmq.close(socket)
zmq.ctx.destroy(context)Correct Usage
The correct way to call zmq.poll() is with a vector:
# This works correctly:
poll_result <- zmq.poll(c(socket), ZMQ.PO()$POLLIN, timeout = 1000)Suggested Fix
The zmq.poll() function should the type of the socket parameter, and convert wrap it in c() if it is an externalptr. (Better yet, add a class to external pointers returned by the package so the code can check that it's getting the right kind of pointer):
if(is(socket, "externalptr")) socket <- c(socket)
Impact
This issue makes debugging ZeroMQ applications unnecessarily difficult, as the error message doesn't point to the actual problem. It's particularly confusing for users coming from other ZeroMQ bindings where polling a single socket doesn't require wrapping it in a vector.
Environment
> sessionInfo()
R version 4.5.1 (2025-06-13)
Platform: x86_64-apple-darwin20
Running under: macOS Sequoia 15.5
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
time zone: America/New_York
tzcode source: internal
attached base packages:
[1] stats graphics grDevices datasets utils methods base
other attached packages:
[1] pbdZMQ_0.3-14
loaded via a namespace (and not attached):
[1] compiler_4.5.1 tools_4.5.1 rstudioapi_0.17.1 renv_1.1.4
>
Additional Notes
This issue was discovered while implementing the ZeroMQ "Lazy Pirate" pattern. The error occurs in common client-server communication scenarios where polling a single socket for responses is a typical use case.