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

Suspend core by default when calling plugin command functions #5112

Merged
merged 7 commits into from
Dec 21, 2024

Conversation

myk002
Copy link
Member

@myk002 myk002 commented Dec 20, 2024

Fixes: #5102
Should be tested with #5075

@myk002 myk002 changed the title Myk coresuspender Suspend core by default when calling plugin command functions Dec 20, 2024
library/PluginManager.cpp Outdated Show resolved Hide resolved
library/PluginManager.cpp Outdated Show resolved Hide resolved
library/modules/Textures.cpp Outdated Show resolved Hide resolved
Copy link
Member

@ab9rf ab9rf left a comment

Choose a reason for hiding this comment

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

as per comments

i am especially not comfortable with adding a core suspender to viewscreen render or logic methods

@myk002
Copy link
Member Author

myk002 commented Dec 20, 2024

as per comments

fixed

i am especially not comfortable with adding a core suspender to viewscreen render or logic methods

what about overlay.cpp, where we call into Lua from render, logic, and feed?

@ab9rf
Copy link
Member

ab9rf commented Dec 20, 2024

what about overlay.cpp, where we call into Lua from render, logic, and feed?

Might be needed there, since that's going to be using the Lua state in Core, which is shared across threads and needs to be arbitrated somehow. I don't know if the lock in the lua_State is sufficient here. @lethosor may be in a better position to offer an opinion here than I am; he is more familiar with that code than I am

update: I looked at the code used in overlay and it uses the lua_State from Core in ways that do not acquire the lock in the state so it does need to be arbitrated. So in this case we need to use some means to arbitrate access to Core::State to prevent two threads from using it simultaneously. We're basically using core suspenders for two not necessarily related purposes here, one to protect from unarbitrated access to DFHack's global state (specifically, the shared Lua state) from more than one thread, and also to protect from unarbitrated access to DF's global state from more than one state. Perhaps these should be distinct mutexes. I don't know.

Copy link
Member

@ab9rf ab9rf left a comment

Choose a reason for hiding this comment

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

Having looked over the CoreSuspender semantics I think this is probably OK.

We do need to ensure that access to the global Lua state is properly arbitrated, but this isn't the PR to do that.

@myk002 myk002 merged commit 5750159 into DFHack:develop Dec 21, 2024
14 checks passed
@myk002 myk002 deleted the myk_coresuspender branch December 21, 2024 00:14
@lethosor
Copy link
Member

lethosor commented Dec 21, 2024

I agree suspending in a vmethod seems very unsafe to me. Did we remove CoreSuspendClaimer? I'm guessing from context that it was intended to be used as a stand-in for CoreSuspender on the render thread to prevent deadlocks. It's possible other things have changed since I Iast looked at this code that make this safer now.

@ab9rf
Copy link
Member

ab9rf commented Dec 21, 2024

Sorry I missed a mistake on review. There's a CoreSuspender in Core::Shutdown that absolutely should not be there

@@ -2416,7 +2416,7 @@ int Core::Shutdown ( void )
d->hotkeythread.join();
d->iothread.join();

CoreSuspendClaimer suspend;
Copy link
Member

@ab9rf ab9rf Dec 21, 2024

Choose a reason for hiding this comment

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

This shouldn't be here at all. This is in Core::Shutdown, the core suspension mechanism has already been dismantled at this point and all DFHack threads, as well as the DF simulation thread, have been terminated. The suspender should be removed entirely since there's nothing to protect against here.

This usage came up when I added instrumentation to detect attempts to acquire a CoreSuspender from the DF render thread, because doing this is unsafe. It happens that DF calls dfhooks_shutdown from the render (main) thread, so the attempt to acquire a CoreSuspender here set off the instrumentation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed in ebac377

@myk002
Copy link
Member Author

myk002 commented Dec 21, 2024

Did we remove CoreSuspendClaimer?

CoreSuspendClaimer has been an alias for CoreSuspender since #1304 (merged in 2018). I just removed the alias to make the now-uniform semantics clearer.

myk002 added a commit that referenced this pull request Dec 21, 2024
@ab9rf
Copy link
Member

ab9rf commented Dec 22, 2024

I'm guessing from context that it was intended to be used as a stand-in for CoreSuspender on the render thread to prevent deadlocks.

it was aliased to CoreSuspender in a 2018 change. Also, there is simply no safe way to use a CoreSuspender from the render thread, or indeed do anything that might block the render thread, without risking a deadlock, because the render thread can be (and often is) blocking the simulation thread. This is why we have the hotkey thread and the hotkey mailslot to move work units from the render thread, which we cannot block, to the hotkey thread, which we can. This allows us to initiate work units that need a suspended core from the render thread in a safe manner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Make plug-in commands run with suspended core
3 participants