c++ - 对于由 startproc 运行的程序,QDir::homePath() 的非预期结果

标签 c++ linux qt

我有如下小程序:

#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: %s\n", qPrintable(QDir::homePath()));
  printf("Native homedir: %s\n", 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

没关系

  • 当通过 startproc 由 root 作为不同的用户运行时,例如startproc -u user/full/path/to/program,输出为:

    Qt homedir: /root
    Native homedir: /home/user

这是好的,或者不是预期的(至少对我而言)

我的问题是:为什么最后一次运行的结果与其他运行的结果不同?它是 Qt 中的一个错误(没有考虑到有效用户与真实用户不同的事实,或者不同的东西),还是我遗漏了一些背景信息(例如 startproc 的工作机制)?

有问题的 Qt 版本是 5.6.1。

最佳答案

Qt 的 QFileSystemEngine 在 Unix 上使用 HOME 环境变量的内容 - 请参阅其 implementation .然而 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();
}

关于c++ - 对于由 startproc 运行的程序,QDir::homePath() 的非预期结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49303486/

相关文章:

c++ - Eclipse CDT 内置包含目录

c++ - Linux/POSIX 相当于 C++ 代码中的 Win32 API TerminateProcess

c++ - QDialog:如何在 Windows 上启用父窗口(主窗口)的后面?

c++ - c++11 有类似 quint8 的东西吗?

c++ - SDL:SDL_WaitEvent 异常?

C++ 指针数组

linux - 杀死命令中特定值位于特定范围之间的进程

qt - QProcess 在调用 QProcess.start() 后退出应用程序

c++ - 如果是一个类的私有(private)数据成员并且我们创建该类的两个对象,那么指向 int 数据类型的指针是什么?

c - 在后台 C linux 中运行一个新的子进程