Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some Memory in Runtime Not Recognized by Garbage Collector #56

Open
dz333 opened this issue Dec 17, 2019 · 4 comments
Open

Some Memory in Runtime Not Recognized by Garbage Collector #56

dz333 opened this issue Dec 17, 2019 · 4 comments
Labels
bug Something isn't working

Comments

@dz333
Copy link
Collaborator

dz333 commented Dec 17, 2019

While both concurrency and reflection are individually supported, calling any of the reflection methods in a multithreaded program can cause segfaults. This is a high priority issue and was introduced when multithreading support was introduced with: #52

@dz333 dz333 added the bug Something isn't working label Dec 17, 2019
@dz333 dz333 changed the title Concurrent Calls to Reflection Has Race Conditions Concurrent Calls to Reflection Cause Race Conditions Dec 17, 2019
@guoyiteng
Copy link
Contributor

guoyiteng commented Dec 20, 2019

In fact, the segfault has nothing to do with multithreading. It can be reproduced with a single-threaded program (test/isolated/ReflectionMemoryTest.java in #57) After digging into this problem several days, I found that it was due to our garbage collector.

There is a warning in the bdwgc documentation as follows

WARNING: pointers inside memory allocated by the standard malloc are not seen by the garbage collector. Thus objects pointed to only from such a region may be prematurely deallocated. It is thus suggested that the standard malloc be used only for memory regions, such as I/O buffers, that are guaranteed not to contain pointers to garbage collectible memory. Pointers in C language automatic, static, or register variables, are correctly recognized. (Note that GC_malloc_uncollectable has semantics similar to standard malloc, but allocates objects that are traced by the collector.)

In our compiler, we sometimes stored the gc allocated memory pointer inside data structures allocated by the standard malloc. Therefore, when the gc started to collect memory, it would mistakenly collect the memory region referenced by these pointers. It explained why it only appeared after thousands of iterations. The memory was used a lot after thousands of iterations so the gc started to work. In addition, I tried to manually invoke GC_gcollect when GC_malloc was invoked. The segfault started to show in the first several iterations. This behavior also confirmed my hypothesis.

However, this type of problem cannot be easily solved by replacing malloc with GC_malloc in our codebase. I tried but failed to do so, because we also stored the pointer to the memory allocated by the gc in other places: memory allocated by std containers such as std::unordered_map and memory allocated by our compiler itself such as dispatch vector, class info, and etc.

  • To resolve the first type of memory, I found the following from bdwgc docs. We could simply include gc_allocator.h, which would override the default allocator in cpp.

Very often it will also be necessary to use gc_allocator.h and the allocator declared there to construct STL data structures. Otherwise subobjects of STL data structures will be allocated using a system allocator, and objects they refer to may be prematurely collected.

  • For the second one, it is much more complicated. We have to instruct the gc how to find the memory region created by our compiler. There is a function GC_add_roots(low_addr, high_addr_plus_1) in bdwgc for this purpose. However, I have no idea how to get the memory region created by our compiler.

In conclusion, this issue is not related to the newly added multithreading support, and I believe it requires some non-trivial work to fix this problem.

@dz333 dz333 changed the title Concurrent Calls to Reflection Cause Race Conditions Some Memory in Runtime Not Recognized by Garbage Collector Dec 20, 2019
@dz333
Copy link
Collaborator Author

dz333 commented Dec 20, 2019

Thanks for the digging Yiteng, I've update the issue title to reflect the actual problem.

@andrewcmyers
Copy link
Member

It sounds like the problem is pointers from data structures that the compiler statically allocates? I would think that a ctor section could be generated to report such data structures to the GC via the call you describe

@guoyiteng
Copy link
Contributor

Yes, I believe this is a reasonable way to resolve this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants