[jdk17] RFR: 8268524: nmethod::post_compiled_method_load_event racingly called on zombie [v2]

Coleen Phillimore coleenp at openjdk.java.net
Tue Jun 22 14:24:38 UTC 2021


On Tue, 22 Jun 2021 14:00:00 GMT, Erik Österlund <eosterlund at openjdk.org> wrote:

>> In the code exercised by JvmtiCodeBlobEvents::generate_compiled_method_load_events, we grab a code cache iterator with the NMethodIterator::only_alive_and_not_unloading mode, under the CodeCache_lock. The idea is to then call post_compiled_method_load_event() on each of these is_alive() nmethods. Surely none of them will be a zombie. Inside of post_compiled_method_load_event() we filter out nmethods that racingly can die, like this:
>> 
>> if (is_not_entrant() && can_convert_to_zombie()) {
>>   return;
>> }
>> 
>> So if the nmethod was dead or is_unloading(), we wouldn't get it into the iterator, and here we explicitly filter out nmethods that can become zombies. Now we should have all bases covered, no way we can end up calling the subsequent code on a zombie!
>> 
>> Except... the code called by the sweeper that flips an nmethod to zombie, doesn't hold the CodeCache_lock. Instead it holds the CompiledMethod_lock, which this JVMTI code does not hold. So between it being alive in the iterator, and calling is_not_entrant(), the nmethod could have racingly already become zombie. So when we check is_not_entrant(), it will return false. Because it's a zombie. Therefore we are tricked into believing the nmethod is safe to post around these events, while in fact it is already dead.
>> 
>> After we have mistakenly grabbed a zombie nmethod, when we use ZGC, we call the nmethod entry barriers on it. It gets indigestion due to being called on a zombie. I'm sure there are more sources of indigestion as well.
>
> Erik Österlund has updated the pull request incrementally with one additional commit since the last revision:
> 
>   fix incomplete comment

Marked as reviewed by coleenp (Reviewer).

src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp line 233:

> 231:       // to ensure the iteration is safe and nmethods are not concurrently freed.
> 232:       // However, they may still change states and become !is_alive(). Filtering
> 233:       // those out is done inside of nmethod::post_compiled_method_load_event().

yes I like this.

-------------

PR: https://git.openjdk.java.net/jdk17/pull/107


More information about the hotspot-compiler-dev mailing list