Workaround static Task destruction error
A task has to get the SchedulerLock to remove itself from the Scheduler list. This doesn't work, if the Task is static, as the static Scheduler might be destroyed earlier. In this case we fail with the following backtrace: #0 SchedulerMutex::acquire #1 Task::~Task #2 __run_exit_handlers Thanks to Michael Stahl to catching this backtrace. As a workaround this marks static tasks, so they ignore the SchedulerMutex in the destructor, We also mark all scheduled Tasks as "static" in DeInitScheduler, as their cleanup was already done. In the end all Tasks should be removed from static objects. Change-Id: I38be3206378b9449193efaccbc96896ac8de9478 Reviewed-on: https://gerrit.libreoffice.org/42574 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
This commit is contained in:
parent
1cfcbf3573
commit
06ce312f79
@ -47,6 +47,7 @@ class VCL_DLLPUBLIC Task
|
|||||||
const sal_Char *mpDebugName; ///< Useful for debugging
|
const sal_Char *mpDebugName; ///< Useful for debugging
|
||||||
TaskPriority mePriority; ///< Task priority
|
TaskPriority mePriority; ///< Task priority
|
||||||
bool mbActive; ///< Currently in the scheduler
|
bool mbActive; ///< Currently in the scheduler
|
||||||
|
bool mbStatic; ///< Is a static object
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void StartTimer( sal_uInt64 nMS );
|
static void StartTimer( sal_uInt64 nMS );
|
||||||
@ -88,6 +89,15 @@ public:
|
|||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
bool IsActive() const { return mbActive; }
|
bool IsActive() const { return mbActive; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function must be called for static tasks, so the Task destructor
|
||||||
|
* ignores the SchedulerMutex, as it may not be available anymore.
|
||||||
|
* The cleanup is still correct, as it has already happened in
|
||||||
|
* DeInitScheduler call well before the static destructor calls.
|
||||||
|
*/
|
||||||
|
void SetStatic() { mbStatic = true; }
|
||||||
|
bool IsStatic() const { return mbStatic; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDED_VCL_TASK_HXX
|
#endif // INCLUDED_VCL_TASK_HXX
|
||||||
|
@ -112,6 +112,7 @@ OLEObjCache::OLEObjCache()
|
|||||||
pTimer = new AutoTimer( "svx OLEObjCache pTimer UnloadCheck" );
|
pTimer = new AutoTimer( "svx OLEObjCache pTimer UnloadCheck" );
|
||||||
pTimer->SetInvokeHandler( LINK(this, OLEObjCache, UnloadCheckHdl) );
|
pTimer->SetInvokeHandler( LINK(this, OLEObjCache, UnloadCheckHdl) );
|
||||||
pTimer->SetTimeout(20000);
|
pTimer->SetTimeout(20000);
|
||||||
|
pTimer->SetStatic();
|
||||||
}
|
}
|
||||||
|
|
||||||
OLEObjCache::~OLEObjCache()
|
OLEObjCache::~OLEObjCache()
|
||||||
|
@ -172,6 +172,13 @@ Since the Scheduler is always handled by the system message queue, there is
|
|||||||
really no more reasoning to stop after 100 events to prevent LO Scheduler
|
really no more reasoning to stop after 100 events to prevent LO Scheduler
|
||||||
starvation.
|
starvation.
|
||||||
|
|
||||||
|
== Drop static inherited or composed Task objects ==
|
||||||
|
|
||||||
|
The sequence of destruction of static objects is not defined. So a static Task
|
||||||
|
can not be guaranteed to happen before the Scheduler. When dynamic unloading
|
||||||
|
is involved, this becomes an even worse problem. This way we could drop the
|
||||||
|
mbStatic workaround from the Task class.
|
||||||
|
|
||||||
== Run the LO application in its own thread ==
|
== Run the LO application in its own thread ==
|
||||||
|
|
||||||
This would probably get rid of most of the MacOS and Windows implementation
|
This would probably get rid of most of the MacOS and Windows implementation
|
||||||
|
@ -160,6 +160,7 @@ void Scheduler::ImplDeInitScheduler()
|
|||||||
pTask->mbActive = false;
|
pTask->mbActive = false;
|
||||||
}
|
}
|
||||||
pTask->mpSchedulerData = nullptr;
|
pTask->mpSchedulerData = nullptr;
|
||||||
|
pTask->SetStatic();
|
||||||
}
|
}
|
||||||
ImplSchedulerData* pDeleteSchedulerData = pSchedulerData;
|
ImplSchedulerData* pDeleteSchedulerData = pSchedulerData;
|
||||||
pSchedulerData = pSchedulerData->mpNext;
|
pSchedulerData = pSchedulerData->mpNext;
|
||||||
@ -548,6 +549,7 @@ Task::Task( const sal_Char *pDebugName )
|
|||||||
, mpDebugName( pDebugName )
|
, mpDebugName( pDebugName )
|
||||||
, mePriority( TaskPriority::DEFAULT )
|
, mePriority( TaskPriority::DEFAULT )
|
||||||
, mbActive( false )
|
, mbActive( false )
|
||||||
|
, mbStatic( false )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,6 +558,7 @@ Task::Task( const Task& rTask )
|
|||||||
, mpDebugName( rTask.mpDebugName )
|
, mpDebugName( rTask.mpDebugName )
|
||||||
, mePriority( rTask.mePriority )
|
, mePriority( rTask.mePriority )
|
||||||
, mbActive( false )
|
, mbActive( false )
|
||||||
|
, mbStatic( false )
|
||||||
{
|
{
|
||||||
if ( rTask.IsActive() )
|
if ( rTask.IsActive() )
|
||||||
Start();
|
Start();
|
||||||
@ -563,9 +566,14 @@ Task::Task( const Task& rTask )
|
|||||||
|
|
||||||
Task::~Task() COVERITY_NOEXCEPT_FALSE
|
Task::~Task() COVERITY_NOEXCEPT_FALSE
|
||||||
{
|
{
|
||||||
SchedulerGuard aSchedulerGuard;
|
if ( !IsStatic() )
|
||||||
if ( mpSchedulerData )
|
{
|
||||||
mpSchedulerData->mpTask = nullptr;
|
SchedulerGuard aSchedulerGuard;
|
||||||
|
if ( mpSchedulerData )
|
||||||
|
mpSchedulerData->mpTask = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assert( nullptr == mpSchedulerData );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||||
|
@ -80,7 +80,7 @@ public:
|
|||||||
maEntries()
|
maEntries()
|
||||||
{
|
{
|
||||||
SetTimeout(1000);
|
SetTimeout(1000);
|
||||||
Stop();
|
SetStatic();
|
||||||
}
|
}
|
||||||
|
|
||||||
~GdiPlusBuffer() override
|
~GdiPlusBuffer() override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user