Ensure one can call DisposeEnvironment during event callbacks.
Previously calling DisposeEnvironment during an event callback would
cause a currently in-use iterator to be invalidated. This could cause
undefined behavior.
Bug: 37283252
Test: ./test/testrunner/testrunner.py --host --jvmti-stress -j40
Change-Id: I49c02b925f0da5d4f66965f0fca21bf8dc83132a
diff --git a/runtime/openjdkjvmti/events.cc b/runtime/openjdkjvmti/events.cc
index 34492a9..521494a 100644
--- a/runtime/openjdkjvmti/events.cc
+++ b/runtime/openjdkjvmti/events.cc
@@ -141,13 +141,21 @@
}
void EventHandler::RegisterArtJvmTiEnv(ArtJvmTiEnv* env) {
- envs.push_back(env);
+ // Since we never shrink this array we might as well try to fill gaps.
+ auto it = std::find(envs.begin(), envs.end(), nullptr);
+ if (it != envs.end()) {
+ *it = env;
+ } else {
+ envs.push_back(env);
+ }
}
void EventHandler::RemoveArtJvmTiEnv(ArtJvmTiEnv* env) {
+ // Since we might be currently iterating over the envs list we cannot actually erase elements.
+ // Instead we will simply replace them with 'nullptr' and skip them manually.
auto it = std::find(envs.begin(), envs.end(), env);
if (it != envs.end()) {
- envs.erase(it);
+ *it = nullptr;
for (size_t i = static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal);
i <= static_cast<size_t>(ArtJvmtiEvent::kMaxEventTypeVal);
++i) {