Open jerrinsg opened 5 years ago
Hi Jerrin, Can you tell me more about the assumption of the parent process's garbage collector? Shouldn't a child process be able to attach a new object to the root pointer so the parent can access it later?
Each Go process maintains in the runtime some state information regarding memory allocation and garbage collection - the current number of live persistent memory objects (say nlive
), the number of persistent memory objects freed up in the last garbage collection cycle (say nfreed
), etc. These stats are maintained in volatile memory.
Whenever the memory allocator allocates an object in the heap, it increments nlive
. And, when a garbage collection cycle is run, the GC decrements nlive
depending on how many objects it freed up. So running a GC cycle will never result in the value of nlive
getting incremented.
When a parent process P
forks a child process C
, each process has its own accounting of the number of live objects - say nliveP
and nliveC
. When C
creates two new persistent memory objects, C
's runtime increments the value of nliveC
. By adding pointers to these objects in the application root pointer, they are also made visible in the parent process. But when P
runs its next GC cycle, it sees that the actual number of live objects is greater than nliveP
which violates the assumptions of the garbage collector.
The test framework does a
cmd.Run()
to runapiCrash
* functions in a child process. These child processes create heap objects in persistent memory and make these new objects visible in the parent process by linking it to the application root pointer. But this violates the assumptions of the parent process's garbage collector. On its next full cycle, the GC finds new objects reachable from the application root pointer that was not allocated in its lifetime and causes the program to crash.