def shim(handler)
      raise ArgumentError, "invalid handler" if !handler.respond_to?(:call)

      @handler_thread = nil
      @handler_dead_signal = Queue.new # used for signaling

      Zactor.fn do |pipe_delegate, _args|
        begin
          @mtx.synchronize do
            @handler_thread = Thread.current
            @pipe = Socket::PAIR.from_ffi_delegate(pipe_delegate)
            @pipe.signal # handshake, so zactor_new() returns
          end
          process_messages(handler)
        rescue Exception
          @exception = $!
        ensure
          signal_shimmed_handler_death
        end
      end
    end
def shim(handler)
      raise ArgumentError, "invalid handler" if !handler.respond_to?(:call)

      @handler_thread = nil
      @handler_dead_signal = Queue.new # used for signaling

      Zactor.fn do |pipe_delegate, _args|
        begin
          @mtx.synchronize do
            @handler_thread = Thread.current
            @pipe = Socket::PAIR.from_ffi_delegate(pipe_delegate)
            @pipe.signal # handshake, so zactor_new() returns
          end
          process_messages(handler)
        rescue Exception
          @exception = $!
        ensure
          signal_shimmed_handler_death
        end
      end
    end
Shims the given handler. The shim is used to do the handshake, to
 {#process_messages}, and ensure we're notified when the handler has
 terminated.

 @param handler [Proc, #call] the handler used to process messages
 @return [FFI::Function] the callback function to be passed to the zactor
 @raise [ArgumentError] if invalid handler given