ScreenSaver: Timeout if window won't lock. Fixes #4260.

If we fail to lock the window in the kInitialTickRate time, quit the thread.
We were deadlocking causing #4260 because you could open several
threads by moving through the screen saver list quickly all trying to lock
the same window at the same time, classic deadlock.
This commit is contained in:
John Scipione 2013-09-02 19:38:48 -04:00
parent fa3651781a
commit d9acbaf0dc
3 changed files with 18 additions and 16 deletions

View File

@ -41,7 +41,7 @@ private:
void _LoadAddOn();
void _CleanUp();
static status_t _ThreadFunc(void* data);
void _Run();
status_t _Run();
BScreenSaver* fSaver;
BWindow* fWindow;

View File

@ -177,20 +177,22 @@ ScreenSaverRunner::_CleanUp()
}
void
ScreenSaverRunner::_Run()
status_t
ScreenSaverRunner::_Run()
{
static const uint32 kInitialTickRate = 50000;
if (fWindow->Lock()) {
status_t lockStatus = fWindow->LockWithTimeout(kInitialTickRate);
if (lockStatus == B_OK) {
fView->SetViewColor(0, 0, 0);
fView->SetLowColor(0, 0, 0);
if (fSaver != NULL)
fHasStarted = fSaver->StartSaver(fView, fPreview) == B_OK;
fWindow->Unlock();
}
} else
return lockStatus;
// TODO: This code is getting awfully complicated and should
// probably be refactored.
uint32 tickBase = kInitialTickRate;
@ -250,6 +252,8 @@ ScreenSaverRunner::_Run()
if (fSaver != NULL)
fSaver->StopSaver();
return B_OK;
}
@ -257,6 +261,5 @@ status_t
ScreenSaverRunner::_ThreadFunc(void *data)
{
ScreenSaverRunner* runner = (ScreenSaverRunner*)data;
runner->_Run();
return B_OK;
return runner->_Run();
}

View File

@ -630,8 +630,9 @@ ModulesView::MessageReceived(BMessage* message)
be_roster->StartWatching(BMessenger(this, Looper()),
B_REQUEST_QUIT);
if (be_roster->Launch(SCREEN_BLANKER_SIG, &fSettings.Message(),
&fScreenSaverTestTeam) == B_OK)
&fScreenSaverTestTeam) == B_OK) {
break;
}
// Try really hard to launch it. It's very likely that this fails
// when we run from the CD, and there is only an incomplete mime
@ -809,19 +810,17 @@ ModulesView::_OpenSaver()
fSettingsView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
fSettingsBox->AddChild(fSettingsView);
if (saver != NULL) {
fSaverRunner->Run();
if (saver != NULL && fSaverRunner->Run() == B_OK)
saver->StartConfig(fSettingsView);
}
if (fSettingsView->ChildAt(0) == NULL) {
// There are no settings at all, we add the module name here to
// let it look a bit better at least.
BPrivate::BuildScreenSaverDefaultSettingsView(fSettingsView,
fSettings.ModuleName()[0] ? fSettings.ModuleName() :
B_TRANSLATE("Blackness"), saver || !fSettings.ModuleName()[0]
? B_TRANSLATE("No options available") :
B_TRANSLATE("Could not load screen saver"));
fSettings.ModuleName()[0] ? fSettings.ModuleName()
: B_TRANSLATE("Blackness"), saver != NULL && !fSettings.ModuleName()[0]
? B_TRANSLATE("No options available")
: B_TRANSLATE("Could not load screen saver"));
}
}