chuckremes / ffi-rzmq

FFI bindings for ZeroMQ so the library can be used under JRuby and other FFI-compliant ruby runtimes
242 stars 62 forks source link

Can't get ipc:// to work #126

Closed black-snow closed 7 years ago

black-snow commented 7 years ago

Following the readme I tried

ctx = ZMQ::Context.new
s   = ctx.socket ZMQ::REQ
s.connect('ipc://test') # 0
s.send_string 'xoxo', 0 # 4

but nothing's received on the rep endpoint.

chuckremes commented 7 years ago

Give me both sides of the program so I can try to reproduce. Also, give me details on what Ruby you are using including version, and the version of libzmq.

black-snow commented 7 years ago

Thanks for your quick reply.

/usr/local/Cellar/zeromq/4.2.2 (76 files, 2.3MB) * Poured from bottle on 2017-02-21 at 11:06:07

ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-darwin15] Rails 4.2.5

Node endpoint:

const zmq = require('zeromq') // npm i zeromq -- should be 4.2.0
let sock = zmq.socket('rep')
process.on('SIGINT', () => sock.close())

sock.bind(`ipc://test`, err => {
    if (err) {
        console.error('binding failed')
        process.exit(1)
    }
    console.log('server up, listening on ipc://test')
})

sock.on('message', (msg) => {
    console.log(`server got: ${msg.toString('utf8')}`)
    let request = msg.toString('utf8')
    sock.send('xyz')
})

// edit: Might as well be an issue with the node endpoint. Using my test-client from inside the directory works just fine but it will stop working when moving one directory up ... wtf // edit2: nvm, that's due to zeromq bein installed locally

chuckremes commented 7 years ago

My sample program to repro your issue succeeds. See here:

require 'ffi-rzmq'

ctx = ZMQ::Context.new

thr = Thread.new do
  sock = ctx.socket ZMQ::REP
  err = sock.bind('ipc://test')
  puts "Failed to bind IPC socket! #{err}" if err != 0
  puts "wait on sock.recv"
  string = ""
  err = sock.recv_string(string)
  puts "err #{err}, string #{string}"
end

puts "sleep a sec while thread spins up"
sleep 2

s   = ctx.socket ZMQ::REQ
s.connect('ipc://test') # 0
s.send_string 'xoxo', 0 # 4
puts "sent"

puts "sleep a sec while we wait for receiver to respond"
sleep 1

Output is:

sleep a sec while thread spins up
wait on sock.recv
sent
sleep a sec while we wait for receiver to respond
err 4, string xoxo

Looks to me like you are using two different processes. You have a Ruby process as the sender and a Node.js process as a receiver. There might be something odd in the interaction via "ipc". Have you tried using a TCP socket instead?

chuckremes commented 7 years ago

By the way, the "err 4" that shows up in the above output just means we received 4 bytes. It's not an error. This was a quick hack. :)

black-snow commented 7 years ago

Thanks for your reply.

Failed to bind IPC socket! -1 in irb :{ Did you use irb?

Gonna try tcp sock now.

// edit: tcp works fine; it's a pity that ipc does not. I'ma get another binding/implementation to see if the error is in the js bindings or here. brb

// edit2: checked pyzmq against node - ipc works; gonna check ffi-rzmq against pyzmq now

// edit3: @chuckremes ffi-rzmq fails to communicate with the node version as well as with the python version via ipc

python server to verify (I used py2.7+)

import zmq
import time

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("ipc://test")

while True:
    message = socket.recv()
    print "Received request: ", message
    time.sleep (1)  
    socket.send("oxox")

Guess this will be hell to debug :{

chuckremes commented 7 years ago

I don't do any of my testing in irb. I put the above code into a text file and ran it.

Since all of the bind/connect logic is in the libzmq C library, there is nothing for me to debug.

I suggest trying a few things with your examples though.

  1. Try swapping which program does the bind and which does the connect. See if it works in one direction but not the other.

  2. While doing 1, stagger which program starts first. First let the program doing the bind start; try it. Then let the program doing the connect start first; try again.

I'll leave this ticket open another week just in case you discover some weird edge condition in this gem.

black-snow commented 7 years ago

I now ran all my tests via file + ruby. No changes.

node bind - ruby connect: nothing received ruby bind - node connect: nothing received In both cases it didn't matter which one I started first.

Weird thing is, ruby won't bind to ipc://whatever if node already bound to ipc://whatever, so at least the binding seems to work somehow. There ain't no way to monitor ipc, eh?

Again, works fine via tcp. Guess I'll have to use tcp then :{ If there's anything I can do to help getting this fixed please let me know.