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 _LoadAddOn();
void _CleanUp(); void _CleanUp();
static status_t _ThreadFunc(void* data); static status_t _ThreadFunc(void* data);
void _Run(); status_t _Run();
BScreenSaver* fSaver; BScreenSaver* fSaver;
BWindow* fWindow; BWindow* fWindow;

View File

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

View File

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