Fix a use-after-free when a SubsEditCtrl is destroyed while the thesaurus is loading

This commit is contained in:
Thomas Goyne 2014-07-10 19:57:19 -07:00
parent 4dc38447dc
commit 548fbd814b
2 changed files with 13 additions and 3 deletions

View file

@ -42,7 +42,7 @@ Thesaurus::Thesaurus()
} }
Thesaurus::~Thesaurus() { Thesaurus::~Thesaurus() {
// Explicit empty destructor needed for scoped_ptr with incomplete types if (cancel_load) *cancel_load = true;
} }
std::vector<Thesaurus::Entry> Thesaurus::Lookup(std::string word) { std::vector<Thesaurus::Entry> Thesaurus::Lookup(std::string word) {
@ -98,11 +98,18 @@ void Thesaurus::OnLanguageChanged() {
LOG_I("thesaurus/file") << "Using thesaurus: " << dat; LOG_I("thesaurus/file") << "Using thesaurus: " << dat;
if (cancel_load) *cancel_load = true;
cancel_load = new bool{false};
auto cancel = cancel_load; // Needed to avoid capturing via `this`
agi::dispatch::Background().Async([=]{ agi::dispatch::Background().Async([=]{
try { try {
auto thes = agi::make_unique<agi::Thesaurus>(dat, idx); auto thes = agi::make_unique<agi::Thesaurus>(dat, idx);
agi::dispatch::Main().Sync([&thes, this]{ agi::dispatch::Main().Sync([&thes, cancel, this]{
if (!*cancel) {
impl = std::move(thes); impl = std::move(thes);
cancel_load = nullptr;
}
delete cancel;
}); });
} }
catch (agi::Exception const& e) { catch (agi::Exception const& e) {

View file

@ -39,6 +39,9 @@ class Thesaurus {
agi::signal::Connection dict_path_listener; agi::signal::Connection dict_path_listener;
/// Thesaurus path change handler /// Thesaurus path change handler
void OnPathChanged(); void OnPathChanged();
bool *cancel_load = nullptr;
public: public:
/// A pair of a word and synonyms for that word /// A pair of a word and synonyms for that word
typedef std::pair<std::string, std::vector<std::string>> Entry; typedef std::pair<std::string, std::vector<std::string>> Entry;