Skip to content

Commit

Permalink
fix: can not install app in chroot
Browse files Browse the repository at this point in the history
this is a temporary solution:
1. allow cache generation failure;
2. disable font cache generation.
  • Loading branch information
dengbo11 committed Jan 7, 2025
1 parent 6ec4093 commit cac16bf
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 14 deletions.
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,16 @@ add_definitions("-DQT_NO_KEYWORDS")
# NOTE(black_desk): Enable Qt logging with context.
add_definitions("-DQT_MESSAGELOGCONTEXT")

# FIXME: Due to a problem with the font cache generation solution
# this feature is temporarily blocked by LINGLONG_FONT_CACHE_GENERATOR and it can be removed later when the solution is clear.
set(ENABLE_FONT_CACHE_GENERATOR
OFF
CACHE BOOL "enable font cache generator")

if(ENABLE_FONT_CACHE_GENERATOR)
add_definitions(-DLINGLONG_FONT_CACHE_GENERATOR)
endif()

# We need to support both Qt5 and Qt6, and according to the Qt documentation, we
# should be using versioned targets and functions. These varible must be set
# before find_package()
Expand Down
13 changes: 12 additions & 1 deletion libs/linglong/src/linglong/builder/linglong_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,10 @@ set -e

// initialize the cache dir
QDir appCache = this->workingDir.absoluteFilePath("linglong/cache");
if (!appCache.mkpath(".")) {
return LINGLONG_ERR("make path " + appCache.absolutePath() + ": failed.");
}
#ifdef LINGLONG_FONT_CACHE_GENERATOR
QDir appFontCache = appCache.absoluteFilePath("fontconfig");
if (!appFontCache.mkpath(".")) {
return LINGLONG_ERR("make path " + appFontCache.absolutePath() + ": failed.");
Expand All @@ -738,6 +742,7 @@ set -e
if (!appFonts.mkpath(".")) {
return LINGLONG_ERR("make path " + appFonts.absolutePath() + ": failed.");
}
#endif
// write ld.so.conf
QFile ldsoconf = appCache.absoluteFilePath("ld.so.conf");
if (!ldsoconf.open(QIODevice::WriteOnly)) {
Expand All @@ -754,6 +759,7 @@ include /opt/apps/@id@/files/etc/ld.so.conf)";
ldsoconf.write(ldRawConf.toUtf8());
// must be closed here, this conf will be used later.
ldsoconf.close();
#ifdef LINGLONG_FONT_CACHE_GENERATOR
// write fonts.conf
QFile fontsConf = appFonts.absoluteFilePath("fonts.conf");
if (!fontsConf.open(QIODevice::WriteOnly)) {
Expand All @@ -767,6 +773,7 @@ include /opt/apps/@id@/files/etc/ld.so.conf)";
</fontconfig>)";
fontsRawConf.replace("@id@", QString::fromStdString(this->project.package.id));
fontsConf.write(fontsRawConf.toUtf8());
#endif

opts.mounts.push_back({
.destination = "/run/linglong/cache",
Expand Down Expand Up @@ -1557,31 +1564,35 @@ utils::error::Result<void> Builder::run(const QStringList &modules,
.source = this->workingDir.absoluteFilePath("linglong/cache").toStdString(),
.type = "bind",
});
#ifdef LINGLONG_FONT_CACHE_GENERATOR
// mount font cache
applicationMounts.push_back(ocppi::runtime::config::types::Mount{
.destination = "/var/cache/fontconfig",
.options = { { "rbind", "rw" } },
.source = this->workingDir.absoluteFilePath("linglong/cache/fontconfig").toStdString(),
.type = "bind",
});
#endif

std::vector<ocppi::runtime::config::types::Hook> generateCache{};
std::vector<std::string> ldconfigCmd = { "/sbin/ldconfig",
"-C",
"/run/linglong/cache/ld.so.cache" };
std::vector<std::string> fontconfiCmd = { "fc-cache", "-f" };
generateCache.push_back(ocppi::runtime::config::types::Hook{
.args = std::move(ldconfigCmd),
.env = {},
.path = "/sbin/ldconfig",
.timeout = {},
});
#ifdef LINGLONG_FONT_CACHE_GENERATOR
std::vector<std::string> fontconfiCmd = { "fc-cache", "-f" };
generateCache.push_back(ocppi::runtime::config::types::Hook{
.args = std::move(fontconfiCmd),
.env = {},
.path = "/bin/fc-cache",
.timeout = {},
});
#endif
options.hooks.startContainer = std::move(generateCache);
options.mounts = std::move(applicationMounts);

Expand Down
2 changes: 2 additions & 0 deletions libs/linglong/src/linglong/cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,12 +664,14 @@ int Cli::run()
.type = "bind",
});

#ifdef LINGLONG_FONT_CACHE_GENERATOR
applicationMounts.push_back(ocppi::runtime::config::types::Mount{
.destination = "/var/cache/fontconfig",
.options = nlohmann::json::array({ "rbind", "ro" }),
.source = *appCache + "/fontconfig",
.type = "bind",
});
#endif

auto container = this->containerBuilder.create({
.appID = curAppRef->id,
Expand Down
45 changes: 34 additions & 11 deletions libs/linglong/src/linglong/package_manager/package_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ PackageManager::removeAfterInstall(const package::Reference &oldRef,
<< tmp.message();
}
if (module == "binary" || module == "runtime") {
auto ret = this->generateCache(oldRef);
auto ret = this->tryGenerateCache(oldRef);
if (!ret) {
qCritical() << ret.error().message();
}
Expand Down Expand Up @@ -691,7 +691,7 @@ QVariantMap PackageManager::installFromLayer(const QDBusUnixFileDescriptor &fd,
return;
}

auto generateCacheRet = this->generateCache(*newRef);
auto generateCacheRet = this->tryGenerateCache(*newRef);
if (!generateCacheRet) {
taskRef.reportError(std::move(generateCacheRet).error());
return;
Expand All @@ -712,7 +712,7 @@ QVariantMap PackageManager::installFromLayer(const QDBusUnixFileDescriptor &fd,
return;
}

auto generateCacheRet = this->generateCache(*newRef);
auto generateCacheRet = this->tryGenerateCache(*newRef);
if (!generateCacheRet) {
taskRef.reportError(std::move(generateCacheRet).error());
return;
Expand Down Expand Up @@ -1027,7 +1027,7 @@ QVariantMap PackageManager::installFromUAB(const QDBusUnixFileDescriptor &fd,
}

this->repo.exportReference(newAppRef);
auto result = this->generateCache(newAppRef);
auto result = this->tryGenerateCache(newAppRef);
if (!result) {
taskRef.updateState(linglong::api::types::v1::State::Failed,
"Failed to generate some cache.\n" + result.error().message());
Expand Down Expand Up @@ -1335,7 +1335,7 @@ void PackageManager::Install(PackageTask &taskContext,
} else {
this->repo.exportReference(newRef);
}
auto result = this->generateCache(newRef);
auto result = this->tryGenerateCache(newRef);
if (!result) {
taskContext.updateState(linglong::api::types::v1::State::Failed,
"Failed to generate some cache.\n" + result.error().message());
Expand Down Expand Up @@ -1570,7 +1570,7 @@ void PackageManager::UninstallRef(PackageTask &taskContext,
<< ref.toString();
}
if (module == "binary" || module == "runtime") {
auto ret = this->generateCache(ref);
auto ret = this->tryGenerateCache(ref);
if (!ret) {
qCritical() << ret.error().message();
}
Expand Down Expand Up @@ -1785,7 +1785,7 @@ void PackageManager::Update(PackageTask &taskContext,
return;
}

auto result = this->generateCache(newRef);
auto result = this->tryGenerateCache(newRef);
if (!result) {
taskContext.updateState(linglong::api::types::v1::State::Failed,
"Failed to generate some cache.\n" + result.error().message());
Expand Down Expand Up @@ -2158,19 +2158,22 @@ utils::error::Result<void> PackageManager::generateCache(const package::Referenc
}

const auto appCache = std::filesystem::path(LINGLONG_ROOT) / "cache" / layerItem->commit;
const auto appFontCache = appCache / "fontconfig";
const std::string appCacheDest = "/run/linglong/cache";
const std::string generatorDest = "/run/linglong/generator";
const std::string ldGenerator = generatorDest + "/ld-cache-generator";
const std::string fontGenerator = generatorDest + "/font-cache-generator";

utils::Transaction transaction;

#ifdef LINGLONG_FONT_CACHE_GENERATOR
const auto appFontCache = appCache / "fontconfig";
const std::string fontGenerator = generatorDest + "/font-cache-generator";
#endif
std::error_code ec;
if (!std::filesystem::exists(appFontCache, ec)) {
if (!std::filesystem::exists(appCache, ec)) {
if (ec) {
return LINGLONG_ERR(QString::fromStdString(ec.message()));
}
if (!std::filesystem::create_directories(appFontCache, ec)) {
if (!std::filesystem::create_directories(appCache, ec)) {
return LINGLONG_ERR(QString::fromStdString(ec.message()));
}
}
Expand All @@ -2191,13 +2194,15 @@ utils::error::Result<void> PackageManager::generateCache(const package::Referenc
.source = appCache,
.type = "bind",
});
#ifdef LINGLONG_FONT_CACHE_GENERATOR
// bind mount font cache
applicationMounts.push_back(ocppi::runtime::config::types::Mount{
.destination = "/var/cache/fontconfig",
.options = nlohmann::json::array({ "rbind", "rw" }),
.source = appFontCache,
.type = "bind",
});
#endif
// bind mount generator
applicationMounts.push_back(ocppi::runtime::config::types::Mount{
.destination = generatorDest,
Expand Down Expand Up @@ -2254,9 +2259,13 @@ utils::error::Result<void> PackageManager::generateCache(const package::Referenc
// font-cache-generator [cacheRoot] [id]
const std::string ldGenerateCmd = ldGenerator + " " + appCacheDest + " " + ref.id.toStdString()
+ " " + currentArch->getTriplet().toStdString();
#ifdef LINGLONG_FONT_CACHE_GENERATOR
const std::string fontGenerateCmd =
fontGenerator + " " + appCacheDest + " " + ref.id.toStdString();
process.args = std::vector<std::string>{ "bash", "-c", ldGenerateCmd + ";" + fontGenerateCmd };
#endif

process.args = std::vector<std::string>{ "bash", "-c", ldGenerateCmd };

// Note: XDG_RUNTIME_DIR is not set in PM, the ll-box will finally fallback to /run/ll-box.
// But PM has no write permission in that place, so we should specific the root path.
Expand All @@ -2275,6 +2284,20 @@ utils::error::Result<void> PackageManager::generateCache(const package::Referenc
return LINGLONG_OK;
}

// FIXME: can not start container since the kernel does not support the CLONE_NEWUSER feature in the
// chroot environment, reference: https://man7.org/linux/man-pages/man2/unshare.2.html. so we allow
// cache generation to fail, skip it when an error occurs, the function can be removed when the
// above problem is solved.
utils::error::Result<void> PackageManager::tryGenerateCache(const package::Reference &ref) noexcept
{
auto ret = generateCache(ref);
if (!ret) {
qWarning() << "failed to generate cache" << ret.error();
}

return LINGLONG_OK;
}

utils::error::Result<void> PackageManager::removeCache(const package::Reference &ref) noexcept
{
LINGLONG_TRACE("remove the cache of " + ref.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ public
utils::error::Result<void>
Prune(std::vector<api::types::v1::PackageInfoV2> &removedInfo) noexcept;
utils::error::Result<void> generateCache(const package::Reference &ref) noexcept;
utils::error::Result<void> tryGenerateCache(const package::Reference &ref) noexcept;
utils::error::Result<void> removeCache(const package::Reference &ref) noexcept;
linglong::repo::OSTreeRepo &repo; // NOLINT
PackageTaskQueue tasks;
Expand Down
6 changes: 4 additions & 2 deletions libs/linglong/src/linglong/runtime/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ utils::error::Result<void> Container::run(const ocppi::runtime::config::types::P
}
ofs << "include /run/linglong/cache/ld.so.conf" << std::endl;
}

#ifdef LINGLONG_FONT_CACHE_GENERATOR
{
std::ofstream ofs(bundle.absoluteFilePath("conf.d/99-linglong.conf").toStdString());
Q_ASSERT(ofs.is_open());
Expand All @@ -167,6 +167,7 @@ utils::error::Result<void> Container::run(const ocppi::runtime::config::types::P
<< std::endl;
ofs << "</fontconfig>" << std::endl;
}
#endif

this->cfg.mounts->push_back(ocppi::runtime::config::types::Mount{
.destination = "/etc/ld.so.conf.d/zz_deepin-linglong-app.conf",
Expand All @@ -176,7 +177,7 @@ utils::error::Result<void> Container::run(const ocppi::runtime::config::types::P
.type = "bind",
.uidMappings = {},
});

#ifdef LINGLONG_FONT_CACHE_GENERATOR
this->cfg.mounts->push_back(ocppi::runtime::config::types::Mount{
.destination = "/etc/fonts/conf.d",
.gidMappings = {},
Expand All @@ -185,6 +186,7 @@ utils::error::Result<void> Container::run(const ocppi::runtime::config::types::P
.type = "bind",
.uidMappings = {},
});
#endif

nlohmann::json json = this->cfg;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ bool Legacy::generate(ocppi::runtime::config::types::Config &config) const noexc
{ "/etc/machine-id", "/etc/machine-id" },
{ "/etc/ssl/certs", "/run/host/etc/ssl/certs" },
{ "/etc/ssl/certs", "/etc/ssl/certs" },
// FIXME: app can not display normally due to missing cjk font cache file,so we need bind
// /var/cache/fontconfig to container. this is just a temporary solution,need to be removed
// when font cache solution implemented
{ "/var/cache/fontconfig", "/var/cache/fontconfig" },
{ "/usr/local/share/fonts", "/usr/local/share/fonts" },
{ "/usr/lib/locale/", "/usr/lib/locale/" },
{ "/usr/share/themes", "/usr/share/themes" },
Expand Down

0 comments on commit cac16bf

Please sign in to comment.