Project

General

Profile

Actions

Bug #8442

closed

sendmesg (blocking) of class BasicSocket is repeatably sent by the ruby kernel

Added by m_josenhans (Michael Josenhans) almost 11 years ago. Updated over 4 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]
Backport:
[ruby-core:55147]

Description

=begin

(1) The error occurs with the method "sendmesg" (blocking) of class BasicSocket on Ruby 2.0.0-p0 (rvm), but does not occur on Ruby 1.9.3-p392 (rvm).
(2) The error does not occur with the method "send" (non-blocking) of class BasicSocket on Ruby 1.9.3-p392 (rvm) and Ruby 2.0.0-p0 (rvm).

The bug can be reproduced with the code attached.

  • For (1) use the code as attached. The send message occurs at line 50 & 51.
  • For (2) comment out line 50 & 51 and uncomment line 52 & 53.

How to reproduce the error:

run:

  • (({ruby halfsync_halfasync.rb}))

on second terminal (unix):

  • (({telnet localhost 10001}))

on Windows use telnet client e.g. putty and make sure to configure putty as passive ("Connection->Telnet->Telnet negotiation mode: Passive")

What the code does:
It implements the halfsync_halfasync design-pattern (see references in the code).

  • An (({EchoAcceptor})) is registered with the reactor to accept connection setup.
  • A thread pool is started waiting for tasks to be retrieved from a shared queue
  • Upon connection-setup of the telnet the (({EchoAcceptor})) is called and registers an (({EchoServerHandler})) with the Reactor to handle data received via the connection from the telnet client.
  • Upon reception of data via the telent connection, the (({EchoServerHandler})) assembles data until a newline (\n or \r\n) is received. When that is received, the whole line is put into the shared queue.
  • The first thread from the thread pool waiting grabs the received data and the socket from the shared queue and in line 50/51 adds the thread-ID, the number of messages handled by that thread and sends it as a reply to the sender using the received socket.

What to expect as output:

  • Upon entering e.g. text "!1234" and pressing return
    On Ruby 1.9.3-p392 on Linux:
  • See the as response the thread ID, the number of messages within the thread and the text.

On Ruby 2.0.0-p0 on Linux:

  • See same as with Ruby 1.9.3-p392 , but when pressing very fast return after entering no text,
    the message of thread-id and number of messages sent will be repeatedly received by the server.
  • As the number of messages is not increased with each sending, it will be repeatedly sent by the ruby kernel (c-code)

On Ruby 2.0.0-p0 on Windows:

  • Nothing is is sent back to the the telnet server, despite the fact that the message had been received at the servers of the thread pool.

  • Everything works file, if instead of blocking send (line 50/51) the non-blocking send (line 52/53) is used. However correct implementation of the halfsync-halfasync pattern, requires reasonably the usage of blocking "send" in thread pool.

I have to apologize that the program to reproduce the error is slightly large and complicated, but I believe that there is value, when ruby is able to run well known design patterns correctly.

Note:
The code does not run with ruby 1.8.7 and Jruby and Rubinius.
=end


Files

halfsync_halfasync.rb (9.86 KB) halfsync_halfasync.rb m_josenhans (Michael Josenhans), 05/24/2013 06:18 AM
Actions #2

Updated by naruse (Yui NARUSE) over 6 years ago

  • Target version deleted (2.6)

Updated by jeremyevans0 (Jeremy Evans) almost 5 years ago

  • Status changed from Open to Feedback
  • Backport deleted (1.9.3: UNKNOWN, 2.0.0: UNKNOWN)

I tried the example program provided on Ruby 2.6 on OpenBSD, and did not experience the issue that you were experiencing with 2.0.0-p0 on Linux. Are you able to recreate the problem you were having with a supported version of Ruby?

In terms of Windows, from some research, Windows doesn't implement sendmsg, but Ruby emulates it using WSASendMsg. The emulation checks for errors that Windows returns, and the fallback if errors are detected but cannot be mapped to a specific exception class is to use EINVAL, which is the error you get when running the program on Windows.

From some basic testing, recvmsg and sendmsg work on Windows for UDP sockets, but do not work for TCP sockets, and your example uses sendmsg on a TCP socket. This appears to be expected as the Windows documentation for WSASendMsg (https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasendmsg) states: The socket descriptor in the s parameter must be opened with the socket type set to SOCK_DGRAM or SOCK_RAW. TCP Sockets are going to use SOCK_STREAM, and as such it appears expected that WSASendMsg would not work on such sockets.

Actions #4

Updated by jeremyevans0 (Jeremy Evans) over 4 years ago

  • Status changed from Feedback to Closed
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0