由 startproc 运行的程序的 QDir::homePath() 的非预期结果

Non-expected result of QDir::homePath() for a program run by startproc

本文关键字:结果 homePath startproc 程序 QDir 运行      更新时间:2023-10-16

>我有以下小程序:

#include <unistd.h>
#include <pwd.h>
#include <QCoreApplication>
#include <QDir>
const char * homeDir()
{
return getpwuid(geteuid())->pw_dir;
}
int main(int argc, char *argv[])
{
printf("Qt homedir: %sn", qPrintable(QDir::homePath()));
printf("Native homedir: %sn", homeDir());
QCoreApplication a(argc, argv);
return a.exec();
}

现在:

  • 当由"普通"用户直接运行时,./program,输出为: Qt homedir:/home/

    user
    Native homedir:/home/usr

这没关系

  • 当直接由 root 运行时,./program,输出为: Qt homedir:/root

    Native homedir:/root

这没关系

  • 当由 root 作为其他用户通过 sudo 运行时,例如sudo -u user ./program,输出为: Qt homedir:/home/user

    Native homedir:/home/user

这没关系

  • 当由 root 以其他用户身份通过 startproc 运行时,例如startproc -u user /full/path/to/program,输出为:Qt homedir:/

    root
    Native homedir:/home/user

这是行的,或者不是预期的(至少对我来说)

我的问题是:为什么最后一次运行给出的结果与其他运行不同?是Qt中的一个错误(没有考虑到有效用户与真实用户不同的事实,或者不同),还是我缺少一些背景信息(例如startproc的工作原理)?

有问题的Qt版本是5.6.1。

Qt的QFileSystemEngine使用Unix上HOME环境变量的内容 - 请参阅其实现。然而startproc -u并没有设定HOME:这就是它失败的原因。

getpwuid调用可能非常昂贵并且可能会阻塞,即通过从LDAP或AD服务器等获取信息,最好自己处理。此外,它不是线程安全的,您应该改用getpwuid_r

实现可能如下所示:

static QString getHomeDir() {
auto const N = sysconf(_SC_GETPW_R_SIZE_MAX);
auto *buffer = std::make_unique<char[]>(N);
passwd pwd;
passwd *result;
getpwuid_r(geteuid(), &pwd, buffer.get(), N, &result);
if (result) {
auto *dir = result->pw_dir;
auto const decoded = QFile::decodeName(dir);
return QDir::cleanPath(decoded);
}
return {};
}
enum class HomeDir { Default, Init };
QString homeDir(HomeDir option = HomeDir::Default) {
// needs a C++11 compiler for thread-safe initialization
static QFuture<QString> home = QtConcurrent::run(getHomeDir);
return (option == HomeDir::Init) ? QString() : home;
};
int main(int argc, char **argv) {
QCoreApplication app(argc, argv);
homeDir(HomeDir::Init);
// do other time-consuming initializations here
QString () << homeDir();
}