diff --git a/core/mmu.cc b/core/mmu.cc index 6b3ed3cf1cf9f2855d29218d2316ab4c5c7416c8..800453603a8cd92a43133de87d4373d6142b3bfd 100644 --- a/core/mmu.cc +++ b/core/mmu.cc @@ -1079,15 +1079,28 @@ void jvm_balloon_vma::fault(uintptr_t fault_addr, exception_frame *ef) { std::lock_guard<mutex> guard(vma_list_mutex); jvm_balloon_fault(_balloon, ef, this); + delete this; } -jvm_balloon_vma::~jvm_balloon_vma() +void jvm_balloon_vma::detach_balloon() { + _balloon = nullptr; // Could block the creation of the next vma. No need to evacuate, we have no pages vma_list.erase(*this); mmu::map_anon(addr(), size(), _real_flags, _real_perm); } +jvm_balloon_vma::~jvm_balloon_vma() +{ + if (_balloon) { + // This is because the JVM may just decide to unmap a whole region if + // it believes the objects are no longer valid. It could be the case + // for a dangling mapping representing a balloon that was already moved + // out. + jvm_balloon_fault(_balloon, nullptr, this); + } +} + // This function marks an anonymous vma as holding the JVM Heap. The JVM may // create mappings for a variety of reasons, not all of them being the heap. // Since we're interested in knowing how many pages does the heap hold (to make diff --git a/include/osv/mmu.hh b/include/osv/mmu.hh index 1ccb18c4ed7cfc7086ac7d2701510633bab24dfb..708540dfc43c24649218fb90f96c984fb1c52249 100644 --- a/include/osv/mmu.hh +++ b/include/osv/mmu.hh @@ -145,6 +145,7 @@ public: virtual void split(uintptr_t edge) override; virtual error sync(uintptr_t start, uintptr_t end) override; virtual void fault(uintptr_t addr, exception_frame *ef) override; + void detach_balloon(); private: balloon *_balloon; unsigned _real_perm; diff --git a/java/jvm_balloon.cc b/java/jvm_balloon.cc index 2318195cbc8ca4e03cff565875fcbef928a42d79..14860a833b2085bf142be6a1a6c5707f3248670f 100644 --- a/java/jvm_balloon.cc +++ b/java/jvm_balloon.cc @@ -138,7 +138,7 @@ size_t balloon::move_balloon(unsigned char *dest, unsigned char *src) void finish_move(mmu::jvm_balloon_vma *vma) { unsigned char *addr = static_cast<unsigned char *>(vma->addr()); - delete vma; + vma->detach_balloon(); balloon_candidates.erase(addr); } @@ -292,7 +292,7 @@ void jvm_balloon_fault(balloon *b, exception_frame *ef, mmu::jvm_balloon_vma *vm WITH_LOCK(balloons_lock) { assert(!balloons.empty()); - if (ef->error_code == mmu::page_fault_write) { + if (!ef || (ef->error_code == mmu::page_fault_write)) { finish_move(vma); return; }