title: How to handle a Thread Issue in ZeroMQ + Ruby?
body: <p>Stumble upon reading <a href="http://zeromq.org/area:faq" rel="nofollow noreferrer">ZeroMQ FAQ</a> about a Thread safety.</p>
  
  <blockquote>
    <p>My multi-threaded program keeps crashing in weird places inside the ZeroMQ library. What am I doing wrong?</p>
    
    <p>ZeroMQ sockets are <strong>not</strong> thread-safe. This is covered in some detail in the Guide.</p>
    
    <p>The short version is that sockets should not be shared between threads. We recommend creating a dedicated socket for each thread.</p>
    
    <p>For those situations where a dedicated socket per thread is infeasible, a socket may be shared if and only if each thread executes a full memory barrier before accessing the socket. Most languages support a Mutex or Spinlock which will execute the full memory barrier on your behalf. </p>
  </blockquote>
  
  <p>My multi-threaded program keeps crashing in weird places inside the ZeroMQ library.<br>
  What am I doing wrong? </p>
  
  <p>Following is my following code:</p>
  
  <pre><code>Celluloid::ZMQ.init
  module Scp
      module DataStore
      class DataSocket
          include Celluloid::ZMQ 
              def pull_socket(socket)
                  @read_socket = Socket::Pull.new.tap do |read_socket|
                      ## IPC socket
                      read_socket.connect(socket)
                  end
              end
  
              def push_socket(socket)
                  @write_socket = Socket::Push.new.tap do |write_socket|
                      ## IPC socket
                      write_socket.connect(socket)
                  end
              end
  
              def run
                  pull_socket and push_socket and loopify!
              end
  
              def loopify!
                  loop {
                     async.evaluate_response(read_socket.read_multipart)
                  }
              end
  
              def evaluate_response(data)
                  return_response(message_id,routing,Parser.parser(data))
              end
  
              def return_response(message_id,routing,object)
                  data = object.to_response
                  write_socket.send([message_id,routing,data])
              end
          end
      end
  end  
  
  DataSocket.new.run 
  </code></pre>
  
  <p>Now, there are couple things I'm unclear off:</p>
  
  <p><strong>1)</strong>  Assuming that <code>async</code> spawns a new <code>Thread</code> ( every time ) and the <code>write_socket</code> is shared between the all threads and ZeroMQ says that their socket is not thread-safe. I certainly see the <code>write_socket</code> running into threads safety issue.<br>
  ( Btw, hasn't faced this issue in all end to end testing thus far. )</p>
  
  <p><strong>Question 1</strong> : Is my understanding correct on this?</p>
  
  <p>To solve this, ZeroMQ asks us to achieve this using Mutex, Semaphore.</p>
  
  <p>Which results in <em>Question 2</em></p>
  
  <p><strong>2)</strong>  Context Switching.</p>
  
  <p>Given a threaded application can context switch anytime.
  Looking at the ffi-rzmq code <code>Celluloid::ZMQ</code> <strong><code>.send()</code></strong> internally calls <a href="https://github.com/chuckremes/ffi-rzmq/blob/master/lib/ffi-rzmq/socket.rb#L263" rel="nofollow noreferrer">send_strings()</a>, which internally called <code>send_multiple()</code></p>
  
  <p><strong>Question 2:</strong> Context Switching can happen ( anywhere ) inside ( even on critical section )  (here)[<a href="https://github.com/chuckremes/ffi-rzmq/blob/master/lib/ffi-rzmq/socket.rb#L510]" rel="nofollow noreferrer">https://github.com/chuckremes/ffi-rzmq/blob/master/lib/ffi-rzmq/socket.rb#L510]</a></p>
  
  <p>This can also lead to a data ordering issue.</p>
  
  <p>Is my following observation correct?</p>
  
  <p><strong>Note:</strong> </p>
  
  <pre><code>Operating system ( MacOS, Linux and CentOS )  
  Ruby - MRI 2.2.2/2.3.0
  </code></pre>