GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
Already on GitHub? Sign in to your account
This fixes http://trac.xbmc.org/ticket/13113
Currently xbmc deadlocks when using xbmcgui.DialogProgress in plugin before we setup DialogProgress in https://github.com/xbmc/xbmc/blob/master/xbmc/filesystem/PluginDirectory.cpp#L481 :
This commit simply adds processing render loop while waiting for plugin results even if we don't show DialogProgress from CPluginDirectory::WaitOnScriptResult.
while waiting for plugin results - process render loop always, not ju…
…st when showing own's plugin progress dialog
Tested and confirmed fixed.
This has the potential for nastiness, so we need to be careful we get things right.
If you're calling a directory, then you're already potentially off-thread here already I think? Perhaps with the current GetDirectory background stuff, we no longer need the progress dialog here at all? Reducing the potential for clashes seems reasonable. @elupus your thoughts?
It should be OK if you're calling from setResolvedURL() which I think is the other spot this kicks in?
My first thought was just that this stuff is not run in main thread anyway.
So should not need to run rendering loop. Ive not looked at the patch yet
though. Will try to Sunday.
well, then current solution should be wrong too becouse line i'm replacing is doing exactly the same (what I'm adding is just doing it also when we don't have progressBar set) - see https://github.com/xbmc/xbmc/blob/master/xbmc/dialogs/GUIDialogProgress.cpp#L97
just as bonus: here's backtrace of deadlock: http://pastebin.com/t889JHQN (in this case it seems I'm editing code that runs through GUI thread - which might not always be the case as You pointed)
Would you consider adding the ability for a plugin to override this progress dialog and create their own as part of this fix.
Reason being is I want to give more feedback to the user for an initial setup which can take a considerable amount of time.
Or at least the ability to set the percentage and lines for the current dialog.
This involves adding python bindings which is not something I know much about ... and this wouldn't really fix this problem.
I believe main problem here is that we should run renderloop just as main application loop. So IMO proper fix would be getting completely rid of CGUIWindowManager::ProcessRenderLoop and instead of current approach - queue background jobs (for time-consuming tasks) / specify callbacks (for dialogs DoModal()) to not block GUI thread (easy to say, heh)
Did some more checks and it seems that g_windowManager.ProcessRenderLoop(false); will only do anything if g_application.IsCurrentThread() is true so it seems safe to use in non-gui threads.
Of course this doesn't look nice so I was just thinking if we could add some kind of callback to IDirectory and then concrete implementations could annouce progress via this callback:
in CPluginDirectory::GetDirectory (or any other implementation) we could do something like:
m_callback->setProgressInfo(true); // this would cause using progress dialog instead of busy dialog in off-thread getdirectory
if (m_callback->abortRequested()) // if user cancels we could smartly stop getting directory (if possible that is)
also, maybe this could allow plugins to provide their own progress info (with more work on python side I guess)
This should be taken care of in master as we no longer throw up the progress.
Actually that doesn't fix this issue - we are blocking gui thread while in loop in CPluginDirectory::WaitOnScriptResult() and script can't finish because it need to progress dialog to close (which can't be done because we aren't processing render loop). I will reopen PR when I'll have nicer fix.
Does it occur only when we're calling the script to setResolvedUrl() ?
I don't know what setResolvedURL does so can't answer that.
This happens when we run CPluginDirectory::WaitOnScriptResult() in app thread (so when we want to run plugin items marked as playable). Look here: https://github.com/XBMC-Addons/plugin.video.the.trailers/blob/master/addon.py#L243 there is called xbmcgui.DialogProgress, but problem is we aren't really running renderloop now, and because of that pDialog.close() will never return (we need renderloop running for that). xbmc.sleep(500) workarounds this by waiting for progress dialog from CPluginDirectory::WaitOnScriptResult to show up (and we start running renderloop there: progressBar->Progress(); ) and then addon "takes over" that dialog and overwrirte dialog labels and progress bar with own data.
IMO proper way would be:
setResolvedURL is a callback for plugin:// URL items that are marked playable, so probably this case.
Right - it's not necessarily the progress bar, rather that we're on app thread but not spinning the process loop. Ofcourse, we have to be here, so that's not really an issue. Given that, I suggest we have a check for app thread, and if so, make sure the app loop is run (i.e. exactly like CDirectory::GetDirectory does).
Whether the progress or busy is used isn't really a big deal IMO - I'd prefer the latter as it's more consistent with other things (it's not cancelable I think?) and is less likely to cause issues with the plugin also throwing up other dialogs (agreed they shouldn't be doing this, but we can't stop them at this point for Frodo).
So, I think just cleaning this up a bit so it's the same as CDirectory::GetDirectory would be the best way forward.