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

JITServerSharedROMClassCache double-initialization after purging all client session data triggers assert #18631

Closed
cjjdespres opened this issue Dec 14, 2023 · 4 comments · Fixed by #18656

Comments

@cjjdespres
Copy link
Contributor

During a purge operation, the JITServer will delete client session data:

// Time for a purge operation.
// Scan the entire table and delete old elements that are not in use
for (auto iter = _clientSessionMap.begin(); iter != _clientSessionMap.end(); ++iter)
{
TR_ASSERT(iter->second->getInUse() >= 0, "_inUse=%d must be positive\n", iter->second->getInUse());
if (iter->second->getInUse() == 0 &&
crtTime - iter->second->getTimeOflastAccess() > oldAge)
{
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "t=%u Server will purge session data for clientUID %llu of age %lld. Number of clients before purge: %u",
(uint32_t)_compInfo->getPersistentInfo()->getElapsedTime(), (unsigned long long)iter->first, (long long)oldAge, size());
ClientSessionData::destroy(iter->second); // delete the client data
_clientSessionMap.erase(iter); // delete the mapping from the hashtable
}
}

It is possible for this operation to delete every entry in the _clientSessionMap. If it does, the next time a client connects, this code will run:

// If this is the first client, initialize the shared ROMClass cache
if (_clientSessionMap.empty())
{
if (auto cache = TR::CompilationInfo::get()->getJITServerSharedROMClassCache())
cache->initialize(jitConfig);
}

However, the shared ROM class cache will have already been created, leading to an assert triggering in initialize():

TR_ASSERT(!isInitialized(), "Already initialized");

I think the purge operation may need to check if _clientSessionMap is empty post-purge, and shut down the shared ROM class cache if it is. You can see that the deleteClientSession() function does this properly:

// If this was the last client, shutdown the shared ROMClass cache
if (_clientSessionMap.empty())
{
if (auto cache = TR::CompilationInfo::get()->getJITServerSharedROMClassCache())
cache->shutdown();
}

@cjjdespres
Copy link
Contributor Author

Attn @mpirvu. I can put up a fix when I get a chance.

@cjjdespres
Copy link
Contributor Author

Just to note what we talked about: it's not immediately obvious that we should shut down the shared ROM class cache once the last client disconnects, so maybe the deleteClientSession() should be changed instead. That might introduce a problem with unbounded growth of the shared ROM class cache for long-running JITServer instances, though.

@mpirvu
Copy link
Contributor

mpirvu commented Dec 14, 2023

The way I am reading the code is the following:

  • the purge operation may delete the last attached client and in that case it calls JITServerSharedROMClassCache::shutdown(bool lastClient)
  • JITServerSharedROMClassCache::shutdown() deletes the entire ROMClassCache including the persistent allocator used for allocating space for ROMClasses. At the very end it sets _persistentMemory = NULL
  • When a new client connects, it checks _clientSessionMap.empty() which is true, and then proceeds to do another cache initialization.
  • Inside JITServerSharedROMClassCache::initialize() there is the assert TR_ASSERT(!isInitialized(), "Already initialized"); but this should not trigger because isInitialized() looks at _persistentMemory field which was set to NULL.

@mpirvu
Copy link
Contributor

mpirvu commented Dec 14, 2023

I think the purge operation may need to check if _clientSessionMap is empty post-purge, and shut down the shared ROM class cache if it is.

I agree with this

cjjdespres added a commit to cjjdespres/openj9 that referenced this issue Dec 19, 2023
The JITServer expects that the shared ROM class cache will have been
initialized only if the _clientSessionMap is empty.

Fixes: eclipse-openj9#18631

Signed-off-by: Christian Despres <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants