Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stream read error

I'm getting this error message under heavy load. Here is code abstract and message from my error log. I tried everything I could think of. Any suggestion would be greatly appreciated.

Procedure tCacheInMemory.StreamValue(Name: String; IgnoreCase: Boolean; Var Stream:     TStringStream);
Var
  i: Integer;
Begin
  i := 0;
  Try
    If Not active Then
      exit;
    arrayLock.BeginRead;
    Try
      i := Search(Name);
      If i > -1 Then Begin
        If fItems[i].value = Nil Then
          exit;
        fItems[i].value.Position := 0;
        Stream.Position := 0;
        Stream.CopyFrom(fItems[i].value, fItems[i].value.Size);
      End;
    Finally
      arrayLock.EndRead;
    End;
  Except { ...execution jumps to here }
    On E: Exception Do Begin
      x.xLogError('LogErrorCacheInMemory.txt', 'StreamValue:' + E.Message + ' ItemsCount:' + IntToStr( High(fItems)) + 'Memory:' + IntToStr(x.GetMemoryInfoMemory) + endLn + 'StreamSize : ' + IntToStr(fItems[i].value.Size) + ' i=' + IntToStr(i) + 'Name: ' + Name);
      Clear;
    End
  End;
End;

Log Entries:

 3/10/2011 10:52:59 AM: StreamValue:Stream read error ItemsCount:7562 Memory:240816
   StreamSize : 43 i=7506 Name: \\xxxxxxxx\WebRoot\\images\1x1.gif
3/10/2011 12:39:14 PM: StreamValue:Stream read error ItemsCount:10172 Memory:345808
   StreamSize : 849 i=10108 Name: \\xxxxxxxx\WebRoot\\css\screen.add.css
3/10/2011 3:45:29 PM: StreamValue:Stream read error ItemsCount:11200 Memory:425464
   StreamSize : 3743 i=11198 Name: \\xxxxxxxx\WebRoot\\JS\ArtWeb.js

P.S.

arrayLock: TMultiReadExclusiveWriteSynchronizer;
 fItems: Array Of rCache;
Type
  rCache = Record
    Name: String;
    value: TStringStream;
    expired: TDateTime;
  End;

And calling function:

Function tCacheInMemory.CacheCheck(cName: String; Out BlobStream: TStringStream):   Boolean;
Begin
Result := False;
   If Not IfUseCache Then
      exit;
    BlobStream.SetSize(0);
    BlobStream.Size := 0;
    StreamValue(trim(cName), True, BlobStream);
    If BlobStream.Size > 0 Then
    Result := True;
End;

`

like image 242
Yuriy Avatar asked Sep 14 '26 18:09

Yuriy


1 Answers

You're not using correct locking. You're acquiring a read lock on the array of cache entries, but once you find the item you want, you modify it. First, you explicitly modify it by assigning its Position property, and then you implicitly modify it by reading from it, which modifies its Position property again. When other code attempts to read from that same cache item, you'll have interference. If the source stream's Position property changes between the time the destination stream calculates how many bytes are available and the time it actually requests to read those bytes, you'll get a stream-read error.

I have a couple pieces of advice related to this:

  • Don't use streams as a storage device in the first place. You're apparently holding the contents of files. You're not going to change those, so you don't need a data structure designed for making sequential changes. Instead, just store the data in simple arrays of bytes: TBytes. (Also, use of TStringStream in particular introduces confusion over whether those strings' encodings are important. A simple file cache shouldn't be concerned with string encodings at all. If you must use a stream, use a content-agnostic class like TMemoryStream.)
  • Don't quell an exception that you haven't actually handled. In this code, you're catching all exception types, logging some information, clearing the cache, and then proceeding as though everything is normal. But you haven't done anything to resolve the problem that triggered the exception, so everything is not normal. Since you're not really handling the exception, you need to make sure it propagates to the caller. Call raise after to call Clear. (And when you log the exception, make sure you log the exception's ClassName value as well as its message.)
like image 193
Rob Kennedy Avatar answered Sep 16 '26 06:09

Rob Kennedy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!