My favorites | Sign in
Project Home Wiki Issues Source
READ-ONLY: This project has been archived. For more information see this post.
Search
for
  Advanced search   Search tips   Subscriptions
Issue 68: Internal GC randomly "free" some still used memory block
1 person starred this issue and may be notified of changes. Back to list
Status:  WontFix
Owner:  ----
Closed:  Jan 2011


 
Reported by sviannay...@free.fr, Oct 4, 2010
Hi,
We periodically encounter crashes in our runtime. After some investigation, it seems we access memory freed by the GC (Data breakpoint occurs in BlockData::ClearRecycled()). Difficult to isolate because if we change some code, the bug disappear (probably depending on how blocks are allocated). A partial solution we found is to periodically call GC_Run(), but whow.. :)
Is there anyone having same problems ? Maybe we're missing something in the GC usage ?


What version of the product are you using? On what operating system?
v2.06.0 / msw, 2.06.1 doesn't seems to fix it.

Please provide any additional information below.

By the way, parsing the code, I found a strange line code. Maye be I didn't figured out its meaning, but I think it's a "typing" or "copy/paste" error. In GCInternal.cpp, method BlockData::Verify(), line 385, there's the following test :

   if ( !(row_flag * IMMIX_ROW_MARKED) )

Shouldn't be "if ( !(row_flag & IMMIX_ROW_MARKED) )" instead (binary and operator instead of multiply) ?

As the issue we have in ClearRecycled() test this flag, we though it could be the pb, but changing it doesn't fix the issue.

Thanks,
Seb

Dec 21, 2010
Project Member #1 gameh...@gmail.com
Thanks for the fix.  The error is in "Verify", which does not normally get called.
As you can guess, it is pretty hard to debug GC errors.
Some ideas are to compile with -debug to see if this fixes the issue.  If it does, then it may be something to do with optimizations.
Another idea is to see if calling GC_Run can break your code - this will make the bug easier to reproduce. You can also change the condition in CheckCollect to force excessive collection to get a more reproducable bug.
Jan 19, 2011
Project Member #2 gameh...@gmail.com
I'm going to close this issue - if you have a specific example, I may be able to help some more.
Status: WontFix
Jan 19, 2011
#3 sviannay...@free.fr
Thanks for your support.
With your help and advices, we found some misusage from our side (maybe to add somewhere in any faq?) :

We added some cpp wrapper function which takes a user callback as a parameter (callback being a haXe function/method), then we stored the "value" passed to cpp wrapped function, and called it later (for async loading purposes for example).

In pseudo-code, the cpp function could look like this

static value s_pCallback;
void MyLoadFunc( some params, value vCallback )
{
  s_pCallback = value;
}

My understanding (and which fixed the issue), is that when leaving the MyLoadFunc() context, vCallback is "marked" as not used anymore and then can be freed by the GC. Then if we call the callback later using the stored s_pCallback value, it can be ptotentially freed by the GC !

We found a way to cicrumvent it, in the haXe calling side, by declaring a static (or member if in a class) variable, such as m_pLoadCallback.
Then, to call the MyLoadFunc(), we now proceed like this :

....
  m_pLoadCallback = LoadCallBackFunc;
  MyLoadFunc( m_pLoadCallback );
....

This way, we ensure the m_pLoadCallback is still referenced and not garbage collected.
I hope my explanations are clear enough, if not don't hesitate to ask me more, but I really think it could be intersting to share with the community.

Thanks again
Seb




Jan 19, 2011
Project Member #4 gameh...@gmail.com
Hi, I fixed this issue in nme (ExternalInterface.cpp) using the "AutoGCRoot", which is designed for exactly this purpose (or you can use the root functions directly). The following code deletes the callback because it is only used once, but you could keep it alive:


AutoGCRoot *sOnCreateCallback = 0;

void OnMainFrameCreated(Frame *inFrame)
{
   value frame = inFrame ? ObjectToAbstract(inFrame) : alloc_null();
   val_call1( sOnCreateCallback->get(),frame );
   delete sOnCreateCallback;
}

value nme_create_main_frame(value *arg, int nargs)
{
   if (!sgIDsInit)
      InitIDs();
   enum { aCallback, aWidth, aHeight, aFlags, aTitle, aIcon, aSIZE };

   sOnCreateCallback = new AutoGCRoot(arg[aCallback]);

   CreateMainFrame(OnMainFrameCreated,
       (int)val_number(arg[aWidth]), (int)val_number(arg[aHeight]),
       val_int(arg[aFlags]), val_string(arg[aTitle]), val_string(arg[aIcon]) );

   return alloc_null();
}

You are right, this could use some more doco.
Your static member method is also sound.

Jan 19, 2011
#5 sviannay...@free.fr
Ok thanks,
I tried to find a way to duplicate the value callback passed as parameter from cpp side but didn't find anyway, the right api seems to be AutoGCRoot()
Thanks for your worl and your precious help !
Seb


Powered by Google Project Hosting