Safely release thread memory

When starting async processes, we need to have a way to stop the process
before releasing memory.  Descoping FOOTPRINT_ASYNC_LOADER while the
threads were still running could cause crashes depending on the memory
structure.  To avoid this we define clear procedures for exiting a
running async processes and call these when exiting.

Fixes: lp:1772909
* https://bugs.launchpad.net/kicad/+bug/1772909
This commit is contained in:
Seth Hillbrand 2018-05-23 08:52:48 -07:00
parent 190d4d6f55
commit cf2a07559d
4 changed files with 47 additions and 12 deletions

View File

@ -181,6 +181,16 @@ bool FOOTPRINT_ASYNC_LOADER::Join()
}
void FOOTPRINT_ASYNC_LOADER::Abort()
{
if( m_list )
{
m_list->StopWorkers();
m_list = nullptr;
}
}
void FOOTPRINT_ASYNC_LOADER::SetCompletionCallback( std::function<void()> aCallback )
{
m_completion_cb = std::move(aCallback);

View File

@ -284,6 +284,11 @@ protected:
* Join worker threads. Part of the FOOTPRINT_ASYNC_LOADER implementation.
*/
virtual bool JoinWorkers() = 0;
/**
* Stop worker threads. Part of the FOOTPRINT_ASYNC_LOADER implementation.
*/
virtual void StopWorkers() = 0;
};
@ -342,6 +347,11 @@ public:
*/
bool Join();
/**
* Safely stop the current process.
*/
void Abort();
/**
* Set a callback to receive notice when loading is complete.
*

View File

@ -143,27 +143,23 @@ bool FOOTPRINT_LIST_IMPL::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxStri
wxMilliSleep( 20 );
}
if( m_progress_reporter )
m_progress_reporter->AdvancePhase();
if( !m_cancelled )
if( m_cancelled )
{
loader.Abort();
}
else
{
if( m_progress_reporter )
{
m_progress_reporter->AdvancePhase();
m_progress_reporter->SetMaxProgress( m_queue_out.size() );
m_progress_reporter->Report( _( "Loading Footprints" ) );
}
loader.Join();
}
if( m_progress_reporter )
m_progress_reporter->AdvancePhase();
if( m_cancelled )
{
m_errors.move_push( std::make_unique<IO_ERROR>
( _( "Loading incomplete; cancelled by user." ), nullptr, nullptr, 0 ) );
if( m_progress_reporter )
m_progress_reporter->AdvancePhase();
}
m_progress_reporter = nullptr;
@ -203,6 +199,23 @@ void FOOTPRINT_LIST_IMPL::StartWorkers( FP_LIB_TABLE* aTable, wxString const* aN
}
}
void FOOTPRINT_LIST_IMPL::StopWorkers()
{
// To safely stop our workers, we set the cancellation flag (they will each
// exit on their next safe loop location when this is set). Then we need to wait
// for all threads to finish as closing the implementation will free the queues
// that the threads write to.
m_cancelled = true;
for( auto& i : m_threads )
i.join();
m_threads.clear();
m_queue_in.clear();
m_count_finished.store( 0 );
m_list_timestamp = 0;
}
bool FOOTPRINT_LIST_IMPL::JoinWorkers()
{
for( auto& i : m_threads )

View File

@ -78,6 +78,8 @@ protected:
FOOTPRINT_ASYNC_LOADER* aLoader, unsigned aNThreads ) override;
bool JoinWorkers() override;
void StopWorkers() override;
/**
* Function loader_job
* loads footprints from m_queue_in.