summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Burrows <dburrows@debian.org>2009-10-10 16:20:14 -0700
committerDaniel Burrows <dburrows@debian.org>2009-10-10 16:20:14 -0700
commitd66df8c7b6cebd8749c7f865bbfa25b56838b6d0 (patch)
tree050c94fc4f369becf5eab6278c91c8d17aaf0eb6
parentd57803a992829806b6ab27bc02f6ca4a9d397a5f (diff)
downloadaptitude-d66df8c7b6cebd8749c7f865bbfa25b56838b6d0.tar.gz
Defensive code: wrap a try...catch around the background changelog setup thread.
-rw-r--r--src/generic/apt/pkg_changelog.cc240
1 files changed, 129 insertions, 111 deletions
diff --git a/src/generic/apt/pkg_changelog.cc b/src/generic/apt/pkg_changelog.cc
index 4b8e5b03..3f39900b 100644
--- a/src/generic/apt/pkg_changelog.cc
+++ b/src/generic/apt/pkg_changelog.cc
@@ -291,137 +291,155 @@ private:
{
log4cxx::LoggerPtr logger(Loggers::getAptitudeChangelog());
- boost::shared_ptr<std::vector<processed_entry> >
- processed_entries(boost::make_shared<std::vector<processed_entry> >());
-
- for(std::vector<entry>::const_iterator it = entries->begin();
- it != entries->end(); ++it)
+ try
{
- const string srcpkg(it->get_srcpkg());
- const string ver(it->get_ver());
- const string section(it->get_section());
- const string name(it->get_name());
- const string title = ssprintf(_("ChangeLog of %s"), name.c_str());
-
- // Try to find a changelog that's already on the system,
- // first. Check each binary package in the source package;
- // for any package that's unpacked, check that the version on
- // the system corresponds to the requested source version, and
- // if it passes look for a changelog.
- pkgSrcRecords source_records(*apt_source_list);
- source_records.Restart();
- pkgSrcRecords::Parser *source_rec = source_records.Find(srcpkg.c_str());
-
- std::vector<std::string> changelog_uris;
-
- if(source_rec != NULL)
- for(const char **binaryIt = source_rec->Binaries();
- binaryIt != NULL && *binaryIt != NULL; ++binaryIt)
- {
- pkgCache::PkgIterator pkg = (*apt_cache_file)->FindPkg(*binaryIt);
- if(!pkg.end() &&
- !pkg.CurrentVer().end() &&
- !pkg.CurrentVer().FileList().end() &&
- pkg->CurrentState != pkgCache::State::NotInstalled &&
- pkg->CurrentState != pkgCache::State::ConfigFiles)
+ boost::shared_ptr<std::vector<processed_entry> >
+ processed_entries(boost::make_shared<std::vector<processed_entry> >());
+
+ for(std::vector<entry>::const_iterator it = entries->begin();
+ it != entries->end(); ++it)
+ {
+ const string srcpkg(it->get_srcpkg());
+ const string ver(it->get_ver());
+ const string section(it->get_section());
+ const string name(it->get_name());
+ const string title = ssprintf(_("ChangeLog of %s"), name.c_str());
+
+ // Try to find a changelog that's already on the system,
+ // first. Check each binary package in the source package;
+ // for any package that's unpacked, check that the version on
+ // the system corresponds to the requested source version, and
+ // if it passes look for a changelog.
+ pkgSrcRecords source_records(*apt_source_list);
+ source_records.Restart();
+ pkgSrcRecords::Parser *source_rec = source_records.Find(srcpkg.c_str());
+
+ std::vector<std::string> changelog_uris;
+
+ if(source_rec != NULL)
+ for(const char **binaryIt = source_rec->Binaries();
+ binaryIt != NULL && *binaryIt != NULL; ++binaryIt)
{
- pkgRecords::Parser &rec(apt_package_records->Lookup(pkg.CurrentVer().FileList()));
- std::string rec_sourcepkg = rec.SourcePkg();
- if(rec_sourcepkg.empty())
- rec_sourcepkg = pkg.Name();
- std::string rec_sourcever = rec.SourceVer();
- if(rec_sourcever.empty())
- rec_sourcever = pkg.CurrentVer().VerStr();
-
- if(rec_sourcepkg == srcpkg &&
- rec_sourcever == ver)
+ pkgCache::PkgIterator pkg = (*apt_cache_file)->FindPkg(*binaryIt);
+ if(!pkg.end() &&
+ !pkg.CurrentVer().end() &&
+ !pkg.CurrentVer().FileList().end() &&
+ pkg->CurrentState != pkgCache::State::NotInstalled &&
+ pkg->CurrentState != pkgCache::State::ConfigFiles)
{
- // Everything passed. Now test to see whether
- // the changelog exists by trying to stat it.
- struct stat buf;
-
- std::string changelog_file = "/usr/share/doc/";
- changelog_file += pkg.Name();
- changelog_file += "/changelog.Debian";
-
- if(stat(changelog_file.c_str(), &buf) == 0)
+ pkgRecords::Parser &rec(apt_package_records->Lookup(pkg.CurrentVer().FileList()));
+ std::string rec_sourcepkg = rec.SourcePkg();
+ if(rec_sourcepkg.empty())
+ rec_sourcepkg = pkg.Name();
+ std::string rec_sourcever = rec.SourceVer();
+ if(rec_sourcever.empty())
+ rec_sourcever = pkg.CurrentVer().VerStr();
+
+ if(rec_sourcepkg == srcpkg &&
+ rec_sourcever == ver)
{
- LOG_TRACE(logger,
- "The changelog for " << name << " " << ver
- << " exists on the system as " << changelog_file);
- changelog_uris.push_back("file://" + changelog_file);
+ // Everything passed. Now test to see whether
+ // the changelog exists by trying to stat it.
+ struct stat buf;
+
+ std::string changelog_file = "/usr/share/doc/";
+ changelog_file += pkg.Name();
+ changelog_file += "/changelog.Debian";
+
+ if(stat(changelog_file.c_str(), &buf) == 0)
+ {
+ LOG_TRACE(logger,
+ "The changelog for " << name << " " << ver
+ << " exists on the system as " << changelog_file);
+ changelog_uris.push_back("file://" + changelog_file);
+ }
+
+ changelog_file += ".gz";
+
+ if(stat(changelog_file.c_str(), &buf) == 0)
+ {
+ LOG_TRACE(logger,
+ "The changelog for " << name << " " << ver
+ << " exists on the system as " << changelog_file);
+ changelog_uris.push_back("gzip://" + changelog_file);
+ }
+
+ // Beware the races here -- ideally we should
+ // parse the returned changelog and check that
+ // the first version it contains is what we
+ // expect. This should be reliable in *most*
+ // cases, though.
}
-
- changelog_file += ".gz";
-
- if(stat(changelog_file.c_str(), &buf) == 0)
- {
- LOG_TRACE(logger,
- "The changelog for " << name << " " << ver
- << " exists on the system as " << changelog_file);
- changelog_uris.push_back("gzip://" + changelog_file);
- }
-
- // Beware the races here -- ideally we should
- // parse the returned changelog and check that
- // the first version it contains is what we
- // expect. This should be reliable in *most*
- // cases, though.
}
}
- }
- string realsection;
+ string realsection;
- if(section.find('/') != section.npos)
- realsection.assign(section, 0, section.find('/'));
- else
- realsection.assign("main");
+ if(section.find('/') != section.npos)
+ realsection.assign(section, 0, section.find('/'));
+ else
+ realsection.assign("main");
- string prefix;
+ string prefix;
- if(srcpkg.size() > 3 &&
- srcpkg[0] == 'l' && srcpkg[1] == 'i' && srcpkg[2] == 'b')
- prefix = std::string("lib") + srcpkg[3];
- else
- prefix = srcpkg[0];
+ if(srcpkg.size() > 3 &&
+ srcpkg[0] == 'l' && srcpkg[1] == 'i' && srcpkg[2] == 'b')
+ prefix = std::string("lib") + srcpkg[3];
+ else
+ prefix = srcpkg[0];
- string realver;
+ string realver;
- if(ver.find(':') != ver.npos)
- realver.assign(ver, ver.find(':')+1, ver.npos);
- else
- realver = ver;
+ if(ver.find(':') != ver.npos)
+ realver.assign(ver, ver.find(':')+1, ver.npos);
+ else
+ realver = ver;
- string uri = ssprintf("http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog",
- realsection.c_str(),
- prefix.c_str(),
- srcpkg.c_str(),
- srcpkg.c_str(),
- realver.c_str());
+ string uri = ssprintf("http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog",
+ realsection.c_str(),
+ prefix.c_str(),
+ srcpkg.c_str(),
+ srcpkg.c_str(),
+ realver.c_str());
- changelog_uris.push_back(uri);
+ changelog_uris.push_back(uri);
- // Check the file cache to see if the HTTP URI is cached (we
- // don't cache local files).
- temp::name cached_result = download_cache->getItem(uri);
- if(cached_result.valid())
- {
- LOG_INFO(logger, "Fetched the changelog of " << name << " " << ver
- << " from the download cache.");
- it->get_callbacks().get_success().get_slot()(cached_result);
- }
- else
- {
- LOG_TRACE(logger, "Will download the changelog of " << name << " " << ver);
- processed_entries->push_back(processed_entry(*it, changelog_uris));
+ // Check the file cache to see if the HTTP URI is cached (we
+ // don't cache local files).
+ temp::name cached_result = download_cache->getItem(uri);
+ if(cached_result.valid())
+ {
+ LOG_INFO(logger, "Fetched the changelog of " << name << " " << ver
+ << " from the download cache.");
+ it->get_callbacks().get_success().get_slot()(cached_result);
+ }
+ else
+ {
+ LOG_TRACE(logger, "Will download the changelog of " << name << " " << ver);
+ processed_entries->push_back(processed_entry(*it, changelog_uris));
+ }
}
- }
- LOG_TRACE(logger, "Starting to download changelogs.");
- k.get_slot()(boost::shared_ptr<download_changelog_manager>(new download_changelog_manager(processed_entries)));
+ LOG_TRACE(logger, "Starting to download changelogs.");
+ k.get_slot()(boost::shared_ptr<download_changelog_manager>(new download_changelog_manager(processed_entries)));
+ }
+ catch(cw::util::Exception &ex)
+ {
+ LOG_FATAL(logger, "Failed to download changelogs: " << ex.errmsg());
+ k.get_slot()(boost::shared_ptr<download_changelog_manager>());
+ }
+ catch(std::exception &ex)
+ {
+ LOG_FATAL(logger, "Failed to download changelogs: " << ex.what());
+ k.get_slot()(boost::shared_ptr<download_changelog_manager>());
+ }
+ catch(...)
+ {
+ LOG_FATAL(logger, "Failed to download changelogs: unexpected exception type");
+ k.get_slot()(boost::shared_ptr<download_changelog_manager>());
+ }
}
};