Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4072559

1.2/green: socket writes hang then corrupt stream when OS buffer fills up

    Details

    • Subcomponent:
    • Resolved In Build:
      1.2beta
    • CPU:
      sparc
    • OS:
      solaris_2.5
    • Verification:
      Not verified

      Description

      Using the 1.2 green threads runtime (on Solaris 2.x, x<6), if a write to a
      socket needs to "block" because the underlying system buffers are full (e.g.
      if the receiver is not consuming data fast enough), the following is likely
      to occur:

      - The writing thread blocks indefinitely (past when it should have woken up
        because the write could continue).

      - When the writing thread does wake up, it resends some data that it has
        already been sent over the socket, corrupting the integrity of the "reliable"
        socket connection to the Java application (although no error is reported).

      This is demonstrated by the attached class "GreenProblem". Compile the class
      and run it with the following command:

      % java GreenProblem 100000

      It creates a simple thread "SlowReceiver" that receives (and counts) bytes
      over a socket connection relatively slowly (a byte at a time), and the main
      thread connects to that socket and writes the specified number of bytes
      relatively quickly (all in one call). The number is big enough to fill up
      the appropriate system buffers, given that the receiver cannot keep up.

      If things work correctly, it should output something like this (potentially
      with progress messages from the async "Updater" thread as well):

      SlowReceiver: server socket created on port 2002
      main: client socket created, writing 100000 bytes...
      SlowReceiver: client socket accepted, reading bytes...
      main: data written with no exception
      SlowReceiver: finished, bytes received: 100000

      indicating that exactly the same number of bytes were received over the
      socket as were written (very good). This correct behavior will occur with
      any version of JDK 1.1, and with a native threads build of JDK 1.2, and
      on green threads JDK 1.2 on Solaris 2.6 Beta (as tested on "shorter.eng").

      With a 1.2 green threads build (like JDK1.2H) on a Solaris 2.5.x machine,
      however, the output will initially look more like this:

      SlowReceiver: server socket created on port 2002
      main: client socket created, writing 100000 bytes...
      SlowReceiver: client socket accepted, reading bytes...
      Updater: bytes received: 43008
      Updater: bytes received: 43008
      Updater: bytes received: 43008
      . . .

      indicating that progress with the data transfer over the socket has stopped
      with the receiving having received only 43008 bytes. This will continue
      indefinitely. The "green thread" handling this "blocking" I/O can be forced
      to wake up, however, by doing a "kill -POLL" on the process, and then the
      transfer will finish with output like this:

      . . .
      Updater: bytes received: 43008
      main: data written with no exception
      SlowReceiver: finished, bytes received: 102048

      indicating that the receiver received more bytes over the socket
      connection than the sender actually sent!

      See the "Comments" section for my understanding of what's going on here, and
      the "Suggested Fix" for what to do about it.

        Attachments

          Activity

            People

            • Assignee:
              brenaudsunw Benjamin Renaud (Inactive)
              Reporter:
              peterjones Peter Jones
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Imported:
                Indexed: