www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How to tell if the GC is running?

reply "Tomer Filiba" <tomerfiliba gmail.com> writes:
I'm writing a logger/tracer that emits a line for every function 
entry/exit. It naturally makes use of the GC, as it manipulates 
strings (and calls to!string on arguments, etc).

Traced functions may be called normally, but sometimes they are 
called from a destructor (during a collection). When the latter 
happens, it gets to my tracer's code, which tries to allocate 
memory, and dies with a SEGFAULT. It seems that it tried to raise 
an exception but failed:

Program received signal SIGSEGV, Segmentation fault.
0x00000000007f406d in _d_throwc ()
(gdb) bt
#0  0x00000000007f406d in _d_throwc ()
#1  0x0000000000835ec8 in onInvalidMemoryOperationError ()
#2  0x0000000000831296 in gc.gc.GC.mallocNoSync() ()
#3  0x0000000000831207 in gc.gc.GC.malloc() ()
#4  0x00000000007f2578 in gc_qalloc ()
#5  0x00000000007f507a in _d_newarrayiT ()
#6  0x0000000000546385 in 
std.array.__T9replicateTAyaZ.replicate() (n=2, s=...) at 
/usr/include/dmd/phobos/std/array.d:1313
#7  0x000000000067a3a7 in 
foo.runtime.tracing.__T9enterFuncTkZ.enterFunc() (_param_1=0, 
funcName=...) at ...
...
#17 0x000000000055d9fd in main ()

First of all, the SEGFAULT seems to be a bug in the GC itself 
which probably deserves a ticket. I'd settle with simply 
disabling my tracer during GC, but there doesn't seem to be any 
way to tell if I'm in a collection or not.

This is what I'm after: 
https://github.com/D-Programming-Language/druntime/blob/master/src/gc/gc.d#L440

Any help would be appreciated.


-tomer
Apr 06 2014
next sibling parent reply "safety0ff" <safety0ff.dev gmail.com> writes:
Please post more of the stack trace, it looks like you're 
allocating while it is running the destructors / finalization 
(#11408.)

https://d.puremagic.com/issues/show_bug.cgi?id=11408
Apr 06 2014
next sibling parent Etienne <etcimon gmail.com> writes:
On 2014-04-06 5:20 PM, Tomer Filiba wrote:
 On Sunday, 6 April 2014 at 16:34:02 UTC, safety0ff wrote:
 Please post more of the stack trace, it looks like you're allocating
 while it is running the destructors / finalization (#11408.)

 https://d.puremagic.com/issues/show_bug.cgi?id=11408

Yes, I know I'm allocating while the GC is collecting. I'm asking how to avoid this situation -- is there some way to tell that the GC is running? -tomer

If the GC is running you get a stack trace with fullcollect() like this: cache-d_d.exe!gc gc Gcx mark(void * this, void * nRecurse, int ptop) Line 2266 C++ cache-d_d.exe!gc gc Gcx mark(void * this, void * ptop) Line 2249 C++ cache-d_d.exe!gc gc Gcx fullcollect() Line 2454 C++ cache-d_d.exe!gc gc GC mallocNoSync(unsigned int this, unsigned int alloc_size, unsigned int * alloc_size) Line 458 C++ cache-d_d.exe!gc gc GC malloc(unsigned int this, unsigned int alloc_size, unsigned int * bits) Line 413 C++
Apr 06 2014
prev sibling parent Rainer Schuetze <r.sagitario gmx.de> writes:
On 06.04.2014 23:20, Tomer Filiba wrote:
 On Sunday, 6 April 2014 at 16:34:02 UTC, safety0ff wrote:
 Please post more of the stack trace, it looks like you're allocating
 while it is running the destructors / finalization (#11408.)

 https://d.puremagic.com/issues/show_bug.cgi?id=11408

Yes, I know I'm allocating while the GC is collecting. I'm asking how to avoid this situation -- is there some way to tell that the GC is running?

If you don't use explicite or scoped destruction, all class object destructors are called from the GC finalization, so you might just call a different function from class destructors. For structs, they are (currently) not finalized if heap allocated, but their destructor is called for struct fields of a class. To implement a check: this is very implementation specific, but the GC has an internal variable "running" that is set during collection. The problem is how to read this variable. This involves accessing the private global _gc in gc.proxy. If you are ok with modifying the runtime, add a method to gc.proxy like this: bool gc_iscollecting() { return _gc.gcx.running; } (you can make this a template function to avoid having to rebuild the library). The even hackier solution is to use the mangled name of the private variable somewhere in your code: import gc.gc; extern(C) extern __gshared gc.gc.GC _D2gc5proxy3_gcC2gc2gc2GC; bool gc_iscollecting() { return _D2gc5proxy3_gcC2gc2gc2GC.gcx.running; } (Depending on the architecture/platform, you might have to remove the leading underscore from that identifier). For both approaches you will have to add druntime/src to your import paths, as the gc modules are not part of the modules in the druntime/import folder.
Apr 08 2014
prev sibling next sibling parent "Tomer Filiba" <tomerfiliba gmail.com> writes:
On Sunday, 6 April 2014 at 16:34:02 UTC, safety0ff wrote:
 Please post more of the stack trace, it looks like you're 
 allocating while it is running the destructors / finalization 
 (#11408.)

 https://d.puremagic.com/issues/show_bug.cgi?id=11408

Yes, I know I'm allocating while the GC is collecting. I'm asking how to avoid this situation -- is there some way to tell that the GC is running? -tomer
Apr 06 2014
prev sibling parent "Tomer Filiba" <tomerfiliba gmail.com> writes:
Etienne: I got a SEGFAULT when the runtime was trying to throw 
the exception. I can't really catch that. Is there some predicate 
I can use before I'm allocating memory?


-tomer

On Sunday, 6 April 2014 at 23:20:24 UTC, Etienne wrote:
 On 2014-04-06 5:20 PM, Tomer Filiba wrote:
 On Sunday, 6 April 2014 at 16:34:02 UTC, safety0ff wrote:
 Please post more of the stack trace, it looks like you're 
 allocating
 while it is running the destructors / finalization (#11408.)

 https://d.puremagic.com/issues/show_bug.cgi?id=11408

Yes, I know I'm allocating while the GC is collecting. I'm asking how to avoid this situation -- is there some way to tell that the GC is running? -tomer

If the GC is running you get a stack trace with fullcollect() like this: cache-d_d.exe!gc gc Gcx mark(void * this, void * nRecurse, int ptop) Line 2266 C++ cache-d_d.exe!gc gc Gcx mark(void * this, void * ptop) Line 2249 C++ cache-d_d.exe!gc gc Gcx fullcollect() Line 2454 C++ cache-d_d.exe!gc gc GC mallocNoSync(unsigned int this, unsigned int alloc_size, unsigned int * alloc_size) Line 458 C++ cache-d_d.exe!gc gc GC malloc(unsigned int this, unsigned int alloc_size, unsigned int * bits) Line 413 C++

Apr 08 2014