[ENH] FastSocketStream-gk

Willem van den Ende squeak at willemvandenende.com
Wed Feb 16 10:23:11 UTC 2005


On Tuesday 15 February 2005 20:43, goran.krampe at bluefish.se wrote:
> Hi!
>
> Willem van den Ende <squeak at willemvandenende.com> wrote:
> > Hi Göran,
> >
> > cool that someone is working on this! Maybe the new FastSocketStream can
> > solve a problem I've been having...
>
> Hope so too. :)
>

>
> Right, the old SocketStream (as I painstakingly describe in the very
> long class comment) swallows exceptions - which IMHO was bad design. You
> can get the same behavior with FSS if you send it "shouldSignal: false"
> but then lots of methods will not honour the timeout (they are carefully
> marked in the method comments, and the class comment describes that
> too). Which is actually the same behavior as the old SocketStream has -
> which also SocketStreamTest verified.

from the class commment:
"The reason for SocketStream to fail is that while it does timeout on a low 
level (#SocketStream>>receiveData doesn't hang forever) - the callers of 
#receiveData sometimes loop - like in #next:, and thus eliminates the 
timeout. "

I guess the SWHttpClient may need changing. It has its own timeoutloop, am I 
correct in assuming timeout handling would be better handled only by 
FastSocketStream? As it is now, it looks like a deadlock waiting to 
happen.... (which might explain the image lockups) (accidentally you can see 
the 'timeoutloop' variable in the bottom of the stacktrace). 

If so, the http client code could be much simpler - call #upToEnd and don't 
bother doing more difficult stuff. By the way, the code in FastSocketStream 
does look simple and understandable :-). Time for more code in the image to 
follow this example.

>
> So it is not the Right Thing to turn off the signals. The Right Thing
> would be to catch the ConnectionClosed and handle it. The only method
> that actually catches ConnectionClosed is #upToEnd because it
> intrinsically must catch it - otherwise it makes very little sense. :)
>
> The failed primitives I have no idea about. Do you have any more info on
> that?

I've had them before. It may be the way SWHttpClient deals with sockets. I put 
a halt in where it might occur. I'll send a stacktrace and save the image 
away to answer any questions you might have. I'm currently waiting for one to 
occurr... Wait. While I was writing this it happened. I added a lengthy 
stacktrace below (MethodContext reportErrorOn: with 5 levels is not really 
enough to see anything about what's going on). If you need more info, let me 
know.

>
> > I'm using a 3.7 image with a /3.7b-5 VM from ian pumarta's site. I used
> > an older vm as well, with the same problems.
>
> Ok. Well, I use that VM too, haven't seen any real problems - but I am
> not running a spider so... :)

Under windows the lockups happen as well. Looking at the http client code, I 
suspect making the simplification using FastSocketStream #upToEnd might make 
the problem disappear. I should have been warned... the SqueakMap comment for 
SWHttpClient said that cleanup work is needed. I'll see what I  can do about 
it later this week.

>
> > The good news is, the FastSocketStream does seem to be faster on sites
> > that are not slow, and I hope it doesn't lock anymore...
>
> Well, that is why I call it FastSocketStream :). It IS faster. The
> implementation is carefully designed to use faster primitives and much
> less copying.

the code looks carefully made!

cheers,


Willem.

>
> > I hope this helps. Keep up the good work!
>
> Thanks, Göran

Stacktrace:

Socket(Object)>>error:
 Receiver: a Socket[destroyed]
 Arguments and temporary variables: 
  aString:  'a primitive has failed'
 Receiver's instance variables: 
  semaphore:  nil
  socketHandle:  nil
  readSemaphore:  nil
  writeSemaphore:  nil
  primitiveOnlySupportsOneSemaphore:  false


Socket(Object)>>primitiveFailed
 Receiver: a Socket[destroyed]
 Arguments and temporary variables: 

 Receiver's instance variables: 
  semaphore:  nil
  socketHandle:  nil
  readSemaphore:  nil
  writeSemaphore:  nil
  primitiveOnlySupportsOneSemaphore:  false


Socket>>primSocketReceiveDataAvailable:
 Receiver: a Socket[destroyed]
 Arguments and temporary variables: 
  socketID:  nil
 Receiver's instance variables: 
  semaphore:  nil
  socketHandle:  nil
  readSemaphore:  nil
  writeSemaphore:  nil
  primitiveOnlySupportsOneSemaphore:  false


Socket>>waitForDataFor:ifClosed:ifTimedOut:
 Receiver: a Socket[destroyed]
 Arguments and temporary variables: 
  timeout:  45
  closedBlock:  [] in Socket>>waitForDataFor: {[ConnectionClosed signal: 
'Connecti...etc...
  timedOutBlock:  [] in Socket>>waitForDataFor: {[ConnectionTimedOut signal: 
'Data...etc...
  deadline:  1956532
 Receiver's instance variables: 
  semaphore:  nil
  socketHandle:  nil
  readSemaphore:  nil
  writeSemaphore:  nil
  primitiveOnlySupportsOneSemaphore:  false


Socket>>waitForDataFor:
 Receiver: a Socket[destroyed]
 Arguments and temporary variables: 
  timeout:  45
 Receiver's instance variables: 
  semaphore:  nil
  socketHandle:  nil
  readSemaphore:  nil
  writeSemaphore:  nil
  primitiveOnlySupportsOneSemaphore:  false


Socket>>receiveDataSignallingTimeout:into:startingAt:
 Receiver: a Socket[destroyed]
 Arguments and temporary variables: 
  timeout:  45
  aStringOrByteArray:  '-calendar-day-nolink Monday">18</td>
<td class="month-cale...etc...
  aNumber:  4718
 Receiver's instance variables: 
  semaphore:  nil
  socketHandle:  nil
  readSemaphore:  nil
  writeSemaphore:  nil
  primitiveOnlySupportsOneSemaphore:  false


FastSocketStream>>receiveData
 Receiver: FastSocketStream[inbuf:16kb/outbuf:4kb]
 Arguments and temporary variables: 

 Receiver's instance variables: 
  recentlyRead:  1573
  scs:  0
  rcs:  22
  socket:  a Socket[destroyed]
  inBuffer:  '-calendar-day-nolink Monday">18</td>
<td class="month-calendar-day-n...etc...
  outBuffer:  'GET /index.cgi/2004/10/%23top HTTP/1.1

accept: text/html

host: ce...etc...
  inNextToWrite:  4718
  outNextToWrite:  1
  lastRead:  0
  timeout:  45
  autoFlush:  true
  bufferSize:  4096
  binary:  false
  shouldSignal:  true


FastSocketStream>>receiveData:
 Receiver: FastSocketStream[inbuf:16kb/outbuf:4kb]
 Arguments and temporary variables: 
  nBytes:  1024
  needToGet:  15805
 Receiver's instance variables: 
  recentlyRead:  1573
  scs:  0
  rcs:  22
  socket:  a Socket[destroyed]
  inBuffer:  '-calendar-day-nolink Monday">18</td>
<td class="month-calendar-day-n...etc...
  outBuffer:  'GET /index.cgi/2004/10/%23top HTTP/1.1

accept: text/html

host: ce...etc...
  inNextToWrite:  4718
  outNextToWrite:  1
  lastRead:  0
  timeout:  45
  autoFlush:  true
  bufferSize:  4096
  binary:  false
  shouldSignal:  true


FastSocketStream>>next:
 Receiver: FastSocketStream[inbuf:16kb/outbuf:4kb]
 Arguments and temporary variables: 
  anInteger:  1024
  start:  nil
 Receiver's instance variables: 
  recentlyRead:  1573
  scs:  0
  rcs:  22
  socket:  a Socket[destroyed]
  inBuffer:  '-calendar-day-nolink Monday">18</td>
<td class="month-calendar-day-n...etc...
  outBuffer:  'GET /index.cgi/2004/10/%23top HTTP/1.1

accept: text/html

host: ce...etc...
  inNextToWrite:  4718
  outNextToWrite:  1
  lastRead:  0
  timeout:  45
  autoFlush:  true
  bufferSize:  4096
  binary:  false
  shouldSignal:  true


SZReadWriteSocketStream>>nextBytes:
 Receiver: a SZReadWriteSocketStream
 Arguments and temporary variables: 
  anInteger:  1024
 Receiver's instance variables: 
  readStream:  FastSocketStream[inbuf:16kb/outbuf:4kb]
  writeStream:  FastSocketStream[inbuf:16kb/outbuf:4kb]


SptHTTPResponse>>readContentLengthBody:
 Receiver: a SptHTTPResponse
 Arguments and temporary variables: 
  aConnection:  a SptHTTPConnection
  total:  8813
  read:  4096
  bytes:  1024
 Receiver's instance variables: 
  statusLine:  'HTTP/1.1 200 Ok'
  headers:  a PluggableLookupTable('cache-control'->'no-cache' 
'content-length'->'...etc...
  bodyStream:  a WriteStream a ByteArray(60 104 116 109 108 62 10 60 104 101 
97 10...etc...
  request:  a SptHTTPRequest


SptHTTPResponse>>readMessageBody:
 Receiver: a SptHTTPResponse
 Arguments and temporary variables: 
  aConnection:  a SptHTTPConnection
 Receiver's instance variables: 
  statusLine:  'HTTP/1.1 200 Ok'
  headers:  a PluggableLookupTable('cache-control'->'no-cache' 
'content-length'->'...etc...
  bodyStream:  a WriteStream a ByteArray(60 104 116 109 108 62 10 60 104 101 
97 10...etc...
  request:  a SptHTTPRequest


SptHTTPResponse>>readResponse:
 Receiver: a SptHTTPResponse
 Arguments and temporary variables: 
  aConnection:  a SptHTTPConnection
  startT:  nil
 Receiver's instance variables: 
  statusLine:  'HTTP/1.1 200 Ok'
  headers:  a PluggableLookupTable('cache-control'->'no-cache' 
'content-length'->'...etc...
  bodyStream:  a WriteStream a ByteArray(60 104 116 109 108 62 10 60 104 101 
97 10...etc...
  request:  a SptHTTPRequest


SptHTTPRequest>>readResponse
 Receiver: a SptHTTPRequest
 Arguments and temporary variables: 
  response:  a SptHTTPResponse
 Receiver's instance variables: 
  connection:  a SptHTTPConnection
  url:  a SptHTTPUrl
  method:  'GET'
  headers:  a PluggableLookupTable('accept'->'text/html' 'host'->'cepslog.com' 
'us...etc...
  responses:  an OrderedCollection(a SptHTTPResponse)
  entity:  nil
  deferredSend:  [] in SptHTTPRequest>>send {[self sendMessages]}
  okBodyStream:  a WriteStream a ByteArray(60 104 116 109 108 62 10 60 104 101 
97 ...etc...
  state:  a SptHTTPSessionState
  flags:  13
  progress:  a SptHTTPProgress
  conf:  a SptHTTPConfiguration
  timeoutLoop:  a Process in Delay>>wait





More information about the Squeak-dev mailing list