06230551.txt 23-Jun-00


Drowning in a sea of 5333 Errors!
Posted by: JOHNROE

HELP!!!

From the outset we've been plaugued by 4660 errors in our
  large VO2 application, and whilst some of our 50+ sites
  have been tollerating it, others are understandably
  getting pretty fed up.
Now we've ported the app to VO2.5 and sure enough, we found
  loads of 5333's caused by nasties from a byegone age, and
  have spent the last three weeks putting right these past
  sins.
However, the app is still remarkably flaky, and is not even
  ready for first testing. Unless we set DyneSize(40), we
  can't keep it up above a couple of minutes --- not a
  pretty sight!
We've studied the stitaution in detail, read Rod da Silva's
  article till we can recite it backwards (almost), and have
  tried just about everything we can think of --- and still
  no joy.
We've opened and altered EVERY binary entity, re-indexed the
  repository, exported and re-imported modules, revisted all
  the dbServers and made sure we close everything properly,
  and set objects to NULL_OBJECT. Still, when the Garbage
  Collector kicks
in, (we have a Garbace Collect button on hand and perform
  the ceremony at will!) its inevitable that the app will
  die almost instantly. All we can imagine is memory
  corruption on a massive scale! Even WipeDynSpace has not
  helped us.
Does anyone have any ideas, or can recommend anything short
  of valium or an extremely sharp knife?
Growing greyer by the day!

John M Roe


RE: Drowning in a sea of 5333 Errors!
Posted by: williem

John,

My understanding about the DynSize function is that it
  allocates pages of dynamic memory that are availably for
  VO. The Garbage collector will try to free up the memory.
  The larger the program, the more dynamic memory you might
  require. I initially went with dynSize(40) based on stuff
  I read from Larry Atkins (ReportPro). You might have to go
  to a higher dynsize to give yourself enough dymamic memory
  to let the garbage collector do it's thing.
On my com programms (using VOCOM or 25's native), I have to
  close out each method with the
if !incollect()
  collectforced()
endif
Otherwise, after the program has ben running for a while, it
  will run out of dynamic memory and abort. Not good when it
  is running under IIS.

Here is the skeleton that I use:
Method somemethod() class myWebService
  LOCAL nRet AS LONGINT
  LOCAL oError AS USUAL
  LOCAL bErrBlock AS CODEBLOCK
  LOCAL oRS AS ADOServer
  LOCAL cSQL AS STRING
  bErrBlock := ErrorBlock({|oErr| _Break(oErr)})
  #IFDEF __DEBUG
    goLogFile:DebugMsg("getting next Distributor Number")
    AltD()
  #ENDIF
  BEGIN SEQUENCE
    nRet := 0
    // make sure that the database is really open
    IF SELF:openDB()
      cSQL := "select LastDistNun from LastDistNum "
      oRS := ADOServer{cSQL,oConn,NIL,NIL,NIL}
      IF oRS:BOF .and. oRS:EOF
        // no records
        BREAK 1
      ENDIF
      nRet := oRS:FIELDGET(#LASTDISTNUM)
      oRS:FIELDPUT(#LASTDISTNUM, nRet)
      oRS:update()
      oRS:Close()
    ELSE
      BREAK 0
    ENDIF
  RECOVER USING oError
    #IFDEF __DEBUG
      goLogFile:DebugMsg("Error retrieving distNum")
    #ENDIF
    IF IsNumeric(oError)
      DO CASE
      CASE oError = 0
        #IFDEF __DEBUG
          goLogFile:DebugMsg("Error opening database")
        #ENDIF
      CASE oError = 1
        #IFDEF __DEBUG
          goLogFile:DebugMsg("Error no records found")
        #ENDIF
      ENDCASE
      nRet :=0
    ELSE
      // pass on the error block
      nRet = -99 // VO runtime Error
      // Eval(bErrBlock, oError)
    ENDIF
  END SEQUENCE
  ErrorBlock(bErrBlock)
  oRS := NULL_OBJECT
  IF !inCollect()
    CollectForced()
  ENDIF
RETURN nRet


RE: Drowning in a sea of 5333 Errors!
Posted by: JOHNROE


Hi Willie

Many thanks for the tips - You've clearly had it bad too!
My collegue and I are about to start hunting around modules
  for any other hidden nasties - redundant defines etc which
  may be hidden, but we'll also take a good look at the
  skeleton you kindly sent.
From the research we've done, it looks as though pointers
  are getting corrupted by the garbage collector - in fact
  we took some ideas from Rod's SDT article, and actually
  saw pointers being changed as the GC did its bit. What we
  can't work out, is how the hell to stop it.
We'll also up the Dynamic Memory, but I'm not sure at what
  point that could cause problems of its own - if the user
  has insufficient RAM, will the whole app fail to run
  anyway? At the moment its split into a 5.2Meg EXE and a
  3.5 meg DLL, so as you can see, there's one hell of a lot
  of work to do!
Anyway, thanx again and I'll keep you informed.

Kindest
John


RE: Drowning in a sea of 5333 Errors!
Posted by: Stefan Dietl

Once (20b) I used a inifile class with api-calls using
  string2psz(cstring). After removing those api-calls by
  using stringalloc(cstring) I got a much more stable app
  with less 4660.
Another stupid mistake I made was to create an order to a
  field not existing in the table. VO will not give an
  error, you can open a bad indexed file many times without
  crashing - but the GC will not forgive You...

Perhaps not really news...
good luck
Stefan


RE: Drowning in a sea of 5333 Errors!
Posted by: JOHNROE

Hi Stefan

We're exploring ALL avenues, so any help is appreciated.

Thanx
John


RE: Drowning in a sea of 5333 Errors!
Posted by: mlincoln

John,

As you may have realized, the problems you are experiencing
  result from dynamic memory being moved by the garbage
  collector thus invalidating a pointer to said memory. You

  should take extra care to review any areas in your code
  that might cause this.
The classic is casting or converting a string to a psz.
  Allocating a true static string using StringAlloc() solves
  this problem. I have some experience with finding these
  type of problems, so if you would like some assistance,
  let me know.

Mark


RE: Drowning in a sea of 5333 Errors!
Posted by: Marek W. Zawolek

Hi,

I in the middle of dealing with a similar problem. Let me
  tell you about some of experiences.
I have a large VO 2.0 application thet was working almost
  fine, only occasionally having some unexpected problems
  that I tracked down to GC messing my arrays to the point
  that for instance ALEN() was reporting thousands of
  elements instead of just a few. With VO 2.5 things went so
  wrong that the application was dying almost every time.
  Playing with VO 2.5 by "try anything" I noticed the
  following:
1. my application was first reading all report definitions
  (my own simple report-writer), macro compiling them end
  executing
2. all the definitions were being stored in collections (1-
  dimensional arrays of objects, each holding all the
  definitions for a single entity)
3. VO 2.0 stopped having ANY problems and VO 2.5 improved
  after (SURPRISE!!!) instead of loading the definitions to
  each object through INIT ther was calling SUPER:INIT (the
  default generic for each object), I leaved INIT as default
  only and I was loading data through another method called
  after the object was instantated. It sounds strange, as it
  should have no effect, but somehow GC was OK in 2.0 and
  less corruptive in 2.5.
4. With 2.5 I noticed that if I run my report with small
  amount of data so GC does not kick-off during the
  reporting and then I run a second report with the large
  amount of data, everything goes fine, but starting with
  large amount of data almost always ends with 5333.
  CollectForced before and after some big operations did not
  help.
So thanks to 2.5 my 2.0 application became absolutly stable,
  but I still cannot have my 2.5 version running.
I KEEP WORKING ON IT!!!
Good luck, I am happy to be in a good company.

Marek


RE: Drowning in a sea of 5333 Errors!
Posted by: JOHNROE

Thanx Marek

Glad to see we're not alone - I just wonder how many folk
  are struggling with this one, or just keeping quiet and

  hoping that it will go away!
There is a big problem with the GC shifting things around
  and we have created a situation where we've seen pointers
  change after the GC's kicked in, exactly as Rod da Silva
  pointed out in his article for SDT.
The big issue is, how exactly do you stop it!
Also, if we use DyneSize to allocate more memory, and stave
  off the problem, what are the guidelines. Should teh
  default size work, or should we experiment and find a
  suitable value.
It would be great if someone could give some definative
  answers, as this is costing us a lot of money now. We are
  trying to ship a big multi-user app to about 50 clients,
  and just daren't send it out. We can't even do our in
  house testing as the app is too unstable. We can mask it
  by ramping up DynSize, but gather that this is not really
  the answer.
Lets just hope that one day someone might come clean on
  this.

Regards
John


RE: Drowning in a sea of 5333 Errors!
Posted by: Marek W. Zawolek

Hallo again,

I really feel better, because for quite a while I thought
  that it is just my sloppy way of programming responsible
  for all this mess.
I have to admit that now when I increased DYNSIZE to 40 my
  VO 2.5 application behaves much better and observing 2.0 I
  noticed that it was much easier with my app to get
  DYNSIZEINFO size over 200 whereas 2.5 always keeps it at
  minimum e.g. 40. My guess is that 2.5 gets into errors
  when it tries to increase DYNSIZE by itself.
As things improved with my app after moving filling objects
  from INIT into some other METHOD called after
  initialization, perhaps you can try to do it with your
  app. Also remember to NULL_ARRAY all your instance arrays
  and NULL_OBJECT all your instance objects in the CLOSE
  method of your objects.
I admit it maybe quite time consuming (it took me days as I
  had plenty of this kind of objects), but otherwise we have
  to wait for 2.5B - it looks like VO gets better with B
  releases.

Good luck
Marek


RE: Drowning in a sea of 5333 Errors!
Posted by: Marek W. Zawolek

Hi John,

"Playing" with VO 2.5 I just noticed that setting your
  memory with DYNSIZE only once may not be enough. It looks

  like VO 2.5 tries to be smart and occasionally it reduces
  dynamic memory later even to 20 instead of 40 set by
  DYNSIZE. Therefore in some critical places I have added
  the following code:
IF DynInfoSize() < 40
  DynSize(40)
ENDIF
The appication behaves much better.

Regards
Marek


RE: Drowning in a sea of 5333 Errors!
Posted by: sburak

Hi John,

in addition to what others say, put this code in your
  Close() Methods
WHILE TRUE
  ApplicationExec( EXECWHILEEVENT )
  IF ! InCollect()
    CollectForced()
    EXIT
  ENDIF
END
This is in my oppinion better then
IF ! InCollect()
  CollectForced()
ENDIF
However, my experience is that most of the 5333/4660 errors
  arrive from bad coding, ie referencing to objects that are
  out od scope etc.
Hope this helps little bit,

Senad Burak


RE: Drowning in a sea of 5333 Errors!
Posted by: JOHNROE

Hi Senad

This sounds a useful tip and its going in right away!

Thanx
John


RE: Drowning in a sea of 5333 Errors!
Posted by: hourant

Hi Senad,

I'm not sure that Collecforced() solves the 5333 error.
AFAIK, this just runs the GC collector to work more often
  than usual. If the coding is properly done you shouldn't
  force the GC to work by yourself.
But this should shows the 5333 error closer to the point
  where the error really is.

I totaly agree with you about the bad coding and the object
  that are out of scope.
We have reduced drasticaly our own 5333 errors with the
  registeraxit and axit method.
Now, when we create an new object, the first things we do is
  to place a registeraxit(self) in its init method and
  create an axit() method that calls a destroy method.
Even if there is nothing to clean, the method is there and I
  can be sure that it will be called by the GC.
Another trick is to display the number on axitregistered
  objects on the status bar. This number should always be
  very low when trese is no opened "object". When you leave
  a window, this value should come down to the value it was
  before opening the window. You should check Geoff Canvas
  sample (I think it's on knowvo.com).
With 2.5x, we have wiped off all the collectforced with used
  to use in 2.0.
Just my 2 cents.

HTH
Eric


RE: Drowning in a sea of 5333 Errors!
Posted by: Paul Bartlett

Senad,

In my experience putting an ApplicationExec() in Window
  close routines can cause other side effects. Users who are
  fast with their mouse can start clicking around the
  application, or even close the app before your child
  window close method has finished.

Best wishes,
Paul Bartlett


RE: Drowning in a sea of 5333 Errors!
Posted by: hourant

Hi John,

Unfortunatly, I cannot give you THE answer to solve the 5333
  errors. Every time I got this error, I have found the
  solution in my own code.
One of our customers reported a 5333 error a few months ago.
  Updating his video drivers solved the problem.
We have quite large applications running and no one has
  reported this error for a long time.
I also think that NT is much more stable than 9x and we
  advice all our users to use this OS

Eric


RE: Drowning in a sea of 5333 Errors!
Posted by: JOHNROE

Hi Eric


Thanks for the info.

Regards

John


RE: Drowning in a sea of 5333 Errors!
Posted by: Arne Ortlinghaus

Hello John,

perhaps you could insert an additional Testfunction which is
  enabled/disabled by a global switch which makes the
  following:
if !_DynCheck()
  MsgError ("Error in Memory " AsString (DynCheckError()))
endif
if !InCollect()
  CollectForced()
endif
And then insert the function in as many places as possible.
  (It makes program much slower) Perhaps you see an error a
  bit earlier. The problem is that if the error happens in
  the garbage collector it is too late to see the reason.
The other thing is that in my opinion there can be still
  problems in arrays that contain objects which are
  referenced in other arrays. Although in our sight every
  thing seem to work quite well at the beginning I had
  problems when buffering too much data in "global arrays"
  with too complex referencing the objects in the array.
  Maybe the garbage collector does not always know what to
  do.
Another thing could be to look at objects that have a
  destroy-Method. Perhaps you can insert a protect-variable
  that disables the second call of the inner part of the
  destroy method.
And perhaps after using a modal dialog or other objects with
  a Destroy-Method that you destroy it yourself and than set
  the variable to Null_Object. And afterwards call the
  testfunction above.

Arne Ortlinghaus


RE: Drowning in a sea of 5333 Errors!
Posted by: JOHNROE

Hi Arne

Thanx for the info - all ideas are welcome. Also the
  DynCheck sounds useful to try.

Kind regards
John


RE: Drowning in a sea of 5333 Errors!
Posted by: TomWalden

John,

FYI, I've finally gotten rid of all but one scenario of my
  "Access Violation" (error codes 50 _{038}_ 5333) problems.
  In addition to using 2.5a1 with it's new fixes, I made the
  following changes in my code that corrected most of the
  problems. I realize that others have mentioned these and
  other suggestions, but these are what finally worked for
  me, so here is my 2 cents worth:
1. I was using global arrays (about 15) for use in all my
  various comboboxes. Instead I made a global oShell object
  and made all those arrays as instance variables in that
  shell class.
2. I strong-typed all of my methods in ALL of my classes. I
  also used the ~"OpenEarly /-" declaration in each of my
  "class - declare method" source code.
3. I made as many LOCAL variable objects early bound as
  possible. Whenever I was through with an object used in a
  method (or function), I would set that object :=
  NULL_OBJECT (especially for dbServer objects) to help the
  garbage collector. When I was through with arrays I also
  set them to NULL_ARRAY ( a biggee ).
4. After setting my NULL assignments (like when closing a
  window), before and after calling a ReportPro object, and
  after calling a ListView:DeleteAll() methd, I inserted the
  following code:
IF !InCollect()
  CollectForced()
ENDIF
I also did a CollectForced() firtst thing in the :Start()
  method of every app.
5. In a third party browser (bBrowser), it did not like
  macro expansion of field names for setting column color
  assignments. I replace the area with the macro logic with
  a large case statement and it works fine now.
Go figure.
The bottom line is that most of the changes were converting
  as much as possible into OOP logic and the other was
  helping out the garbage collector. Although I still think
  that VO has some memory handling problems, at least almost
  everything is working right now due to some coding
  changes.

HTH,
Tom

RE: Drowning in a sea of 5333 Errors!
Posted by: mrg17

Do you ever write code like
FOo(x:=y(),z) ?
If you look on the news groups you will see I posted last
  week (I have been away since) about a problem that if y()
  triggers the GC then Z (not x) is invalidated.
This seems to have help A LOT with out 5333 problem.
Note that we detected this using many things but IsDynPtr
  was a great help.

    Source: geocities.com/n_s_wong/vo/ng

               ( geocities.com/n_s_wong/vo)                   ( geocities.com/n_s_wong)