Skip to content

Minimal change to get Chakra consistently shutting down properly - #146

Merged
syntheticmagus merged 9 commits into
BabylonJS:masterfrom
syntheticmagus:chakraShutdownFix
Feb 6, 2020
Merged

Minimal change to get Chakra consistently shutting down properly#146
syntheticmagus merged 9 commits into
BabylonJS:masterfrom
syntheticmagus:chakraShutdownFix

Conversation

@syntheticmagus

Copy link
Copy Markdown
Contributor

Contains some...questionable options. Not sure if this should be checked in or not, but it's probably worth discussing at least. There are fixes in here for three separate problems that were causing Chakra to either fail to shut down or to shut down improperly. I'll call each of the problems/fixes out in comments and explain whether/why iffy about the alternative presented.

…n properly. Contains some...questionable options.
{
Log(L"Failed to dispose runtime with error code (%u)\n", errorCode);
}
ThrowIfFailed(JsSetCurrentContext(JS_INVALID_REFERENCE));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First and least controversial change, allows Chakra to shut down correctly. I have not yet confirmed that this resolves the memory leak we were seeing before as there's a problem I just found with refresh; I'll update this comment when I fix that and confirm (or otherwise).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the problems with refresh. Tested to confirm that refresh works, and has consistent and sane memory behavior, on Win32-Chakra, Win32-V8, and UWP-Chakra. UWP-V8 builds but does not run, which seems to be no change from master.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UWP-V8 builds but does not run

Do we have an issue for this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -33,6 +33,37 @@ namespace Babylon
{
namespace
{

@syntheticmagus syntheticmagus Jan 31, 2020

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely the weirdest "fix" in here, and the one I'm least sure about. bgfx doesn't seem to have a mechanism for asking it whether it's alive or not, but some JavaScript-owned objects (relevantly the ProgramData) can end up being destroyed after NativeEngine has already been destroyed and bgfx::shutdown has consequently already been called. They could also theoretically survive long enough to last into another bgfx initialization (if that's possible), which would be disastrous as their handles would now point to things inside bgfx that were really created and owned by somebody else. This global state holder was created to keep track of this. I'm not a fan of it, however, so please let me know of whatever other ideas you'd like to discuss.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are 2 resources to free here : the bgfx shader handle and the JS object. I'd try to keep a list of ProgramData (register in ctor, unregister in dtor). When bgfx::shutdown is called, I'd run thru all the registered ProgramData and free their bgfx handle. I'd then let JS engine free the ProgramData when ever it needs to. I think the same mechanism happens with TextureData. I prefer to be pro active in destruction than trying to determine a state(m_isBgfxInitialized/m_bgfxInitializationId) where I can or can't do something. The more states, the more potential bugs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely agree that that's cleaner, and it seems the ticketed mechanism can be adapted for this purpose. I've refactored to try this other approach.

void Resize(size_t newWidth, size_t newHeight);

using OnResizeCallback = std::function<void(size_t, size_t)>;
using OnResizeCallbackTicket = arcana::ticketed_collection<OnResizeCallback>::ticket;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The third and middle-est change removes the dependency on Arcana's ticketed_collection and just makes a small bespoke alternative instead. This was to get around the order-of-destruction problem described in #142, which we should still consider how to deal with long-term but may not be as tricky as I thought at first. In this particular case, all that's necessary to allow the NativeWindow and NativeEngine to be destroyed in arbitrary orders is for the OnResizeCallbackTicket to simply do nothing if the collection it came from was destroyed before it was. arcana::ticketed_collection doesn't support this, and adding that is a work-in-progress due to the fact that ticketed_collection is supposed to be thread-safe. But thread-safety isn't a concern here as these are both Babylon Native plugins that should only talk to each other on the same thread, so we can get away with doing something simpler. (And we can always move back to the Arcana type when it's ready, if we want to.)

…emory behavior (on the default experience) on Win32-Chakra, Win32-V8, and UWP-Chakra. UWP-V8 builds but is unable to start, which represents no change from master.
Comment thread Library/Source/NativeEngine.cpp Outdated
};

return Napi::External<ProgramData>::New(info.Env(), programData, finalizer);
auto* programDataPtr = programData.get();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rawProgramData

{
Log(L"Failed to dispose runtime with error code (%u)\n", errorCode);
}
ThrowIfFailed(JsSetCurrentContext(JS_INVALID_REFERENCE));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UWP-V8 builds but does not run

Do we have an issue for this?

Comment thread Library/Source/ticketed_collection.h Outdated
m_collection.erase(m_isCollectionStillAlive);
}

delete m_isCollectionStillAlive;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: check nullptr?

{
// NOTE: This type is not thread-safe.
template<typename T>
class ticketed_collection

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should prevent copy and move semantics

Comment thread Library/Source/ticketed_collection.h Outdated
Comment on lines +46 to +47
bool* m_isCollectionStillAlive{};
MapT& m_collection;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed this offline. I would recommend using a double pointer here instead.

@syntheticmagus
syntheticmagus merged commit d20ca12 into BabylonJS:master Feb 6, 2020
@syntheticmagus
syntheticmagus deleted the chakraShutdownFix branch February 6, 2020 00:15
CedricGuillemet added a commit to CedricGuillemet/BabylonNative that referenced this pull request Sep 2, 2026
371d90098b Use zero depth to mean not a volume texture. (BabylonJS#150)
b8cef564e3 texturec: Added positional arguments. (BabylonJS#149)
3b4baab012 Add BC4S, BC5S, BC6HU, RGB10A2U and D32FS8 texture formats. (BabylonJS#148)
0a64629d9f Updated tintexr. (BabylonJS#147)
e95c449452 Updated stb_image. (BabylonJS#146)
da38bface6 Fixed bounds check, and EXR channel pixel type. (BabylonJS#145)
be16d98e34 Updated simplewebp. (BabylonJS#144)

git-subtree-dir: Dependencies/bimg
git-subtree-split: 371d90098b1fd017cd00205979d5ef74b8c3ed62
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 this pull request may close these issues.

3 participants