Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0000434OCamlCamlIDLpublic2001-07-13 19:332001-07-30 16:26
Reporteradministrator 
Assigned To 
PrioritynormalSeverityminorReproducibilityalways
StatusclosedResolutionfixed 
PlatformOSOS Version
Product Version 
Target VersionFixed in Version 
Summary0000434: camlidl: problem with GC (2)
DescriptionFull_Name: Dmitry Bely
Version: camlidl current cvs
OS: Windows NT 4.0
Submission from: d207.p3.col.ru (195.210.132.207)


From my PR#431:

> Unfortunately I cannot create small test example that demonstrates the bug.
But
> I can suppose that it happens because GC moves in memory the caml object
> representing the interface, which obviously is not acceptable. Can this be
true?
> If yes, could you fix it?

Of course moving caml object in memory by GC is very correct (I was wrong), and
is traced via register_global_root(), but nonetheless the bug exists there. I've
managed to isolate it myself. comintf.c from camlidl's runtime contains he
following code:

[---cut---]
static void camlidl_finalize_interface(value intf)
{
  interface IUnknown * i = (interface IUnknown *) Field(intf, 1);
  i->lpVtbl->Release(i);
}

value camlidl_pack_interface(void * intf, camlidl_ctx ctx)
{
  value res = alloc_final(2, camlidl_finalize_interface, 0, 1);
  Field(res, 1) = (value) intf;
  if (ctx != NULL && (ctx->flags & CAMLIDL_ADDREF)) {
    struct IUnknown * i = (struct IUnknown *) intf;
    i->lpVtbl->AddRef(i);
  }
  return res;
}

...

ULONG STDMETHODCALLTYPE camlidl_Release(struct camlidl_intf * this)
{
  struct camlidl_component * comp = this->comp;
  ULONG newrefcount = InterlockedDecrement(&(comp->refcount));
  int i;

  if (newrefcount == 0) {
    for (i = 0; i < comp->numintfs; i++) {
      struct camlidl_intf * intf = &(comp->intf[i]);
      remove_global_root(&(intf->caml_object));
      if (intf->typeinfo != NULL) {
        struct IUnknown * i = (struct IUnknown *) intf->typeinfo;
        i->lpVtbl->Release(i);
      }
    }
    stat_free(comp);
    InterlockedDecrement(&camlidl_num_components);
  }
  return newrefcount;
}
[---cut---]

The problem is that camlidl_finalize_interface() may be invoked when GC moves
object in memory, calling i->lpVtbl->Release(i) (in fact camlidl_Release()) and
decrementing reference counter. It becomes equal to zero and the memory,
occupied by the interface, is incorrectly reclaimed via stat_free(comp). That's
the bug.

I temporarily removed i->lpVtbl->Release(i) from camlidl_finalize_interface()
and the crash disappeared (memory leak is better than the crash :-)). Now I am
waiting for the correct fix from you :-) (BTW, why *both*
camlidl_pack_interface() and camlidl_unpack_interface() increment reference
counter via AddRef()? I cannot understand that ...)

TagsNo tags attached.
Attached Files

- Relationships

-  Notes
(0000060)
administrator (administrator)
2001-07-30 16:26

See PR#433

- Issue History
Date Modified Username Field Change
2005-11-18 10:13 administrator New Issue


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker