[Libwebsockets] [libwebsockets] #16: Early close of large stream under load

Trac trac at libwebsockets.org
Sat Feb 16 01:56:13 CET 2013


#16: Early close of large stream under load
------------------------------------+--------------------
 Reporter:  dbrnz                   |      Owner:  agreen
     Type:  defect                  |     Status:  new
 Priority:  major                   |  Milestone:
Component:  libwebsocket test apps  |    Version:
 Keywords:                          |
------------------------------------+--------------------
 I'm sending approx 5MB of data broken into approx 16K blocks (by my
 protocol), from a Tornado server to a libwebsockets client. All is well
 running a single test process.

 However, with concurrent sends, data is sometimes lost. When this happens
 there is unprocessed received data at LWS_CALLBACK_CLOSED time. In my code
 I have:
 {{{
  case LWS_CALLBACK_CLOSED:
   fprintf(stderr,
     "%s: socket closed, state=%d, blocks=%d, last_process=%d, (%d, %ld,
 %d, %d)\n",
     run_id, sd->state, sd->sp->number, last_process,
     ws->u.ws.rx_user_buffer_head,
     ws->u.ws.rx_packet_length,
     ws->u.ws.rxflow_len,
     ws->u.ws.rxflow_pos) ;
   if (last_process != 16210) fprintf(stderr, "%s: SHORT BLOCK...\n",
 run_id) ;
 }}}
 where `last_process` is a count of bytes seen by
 LWS_CALLBACK_CLIENT_RECEIVE for the current block; for my test download
 this should be 16210.

 The result of running eight downloads, each as separate processes under
 bash, is:
 {{{
 1: socket closed, state=2, blocks=226, last_process=16210, (0, 0, 0, 0)
 1: last block: 227, last frame: 650000
 4: socket closed, state=2, blocks=226, last_process=16210, (0, 0, 0, 0)
 4: last block: 227, last frame: 650000
 3: socket closed, state=2, blocks=226, last_process=12288, (3869, 53, 0,
 0)
 3: SHORT BLOCK...
 3: last block: 226, last frame: 648000
 6: socket closed, state=2, blocks=226, last_process=12288, (3058, 864, 0,
 0)
 6: SHORT BLOCK...
 6: last block: 226, last frame: 648000
 5: socket closed, state=2, blocks=226, last_process=16210, (0, 0, 0, 0)
 5: last block: 227, last frame: 650000
 7: socket closed, state=2, blocks=226, last_process=16210, (0, 0, 0, 0)
 7: last block: 227, last frame: 650000
 8: socket closed, state=2, blocks=226, last_process=16210, (0, 0, 0, 0)
 8: last block: 227, last frame: 650000
 2: socket closed, state=2, blocks=226, last_process=16210, (0, 0, 0, 0)
 2: last block: 227, last frame: 650000
 }}}

 Processes 3 and 4 have unprocessed data, with `rx_user_buffer_head` and
 `rx_packet_length` both non-zero.
 `(last_process+rx_user_buffer_head+rx_packet_length) == 16210`, so all
 data has been received by libwebsockets (plus I have a wireshark capture
 that confirms this).

 This is reproducible, provided there are enough concurrent downloads. My
 guess is that with CPU loading the remote close() is actioned before all
 data has been sent to LWS_CALLBACK_CLIENT_RECEIVE.

-- 
Ticket URL: <http://libwebsockets.org/trac/ticket/16>
libwebsockets <http://libwebsockets.org>
libwebsockets C library



More information about the Libwebsockets mailing list