qt 6.6.0 clean

This commit is contained in:
kleuter
2023-11-01 22:23:55 +01:00
parent 7b5ada15e7
commit 5d8194efa7
1449 changed files with 134276 additions and 31391 deletions

View File

@ -28,3 +28,6 @@ if(WIN32)
add_subdirectory(testProcessEchoGui)
add_subdirectory(testSetNamedPipeHandleState)
endif()
if(UNIX)
add_subdirectory(testUnixProcessParameters)
endif()

View File

@ -0,0 +1,58 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2020 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#if defined(_MSC_VER)
# include <intrin.h>
#endif
#if __has_include(<signal.h>)
# include <signal.h>
#endif
#if __has_include(<sys/resource.h>)
# include <sys/resource.h>
#endif
#ifndef __has_builtin
# define __has_builtin(x) 0
#endif
namespace tst_QProcessCrash {
struct NoCoreDumps
{
#if defined(RLIMIT_CORE)
struct rlimit rlim;
NoCoreDumps()
{
if (getrlimit(RLIMIT_CORE, &rlim) == 0 && rlim.rlim_cur != 0) {
struct rlimit newrlim = rlim;
newrlim.rlim_cur = 0;
setrlimit(RLIMIT_CORE, &newrlim);
}
}
~NoCoreDumps()
{
setrlimit(RLIMIT_CORE, &rlim);
}
#endif // RLIMIT_CORE
};
void crashFallback(volatile int *ptr = nullptr)
{
*ptr = 0;
}
void crash()
{
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
__ud2();
#elif __has_builtin(__builtin_trap)
__builtin_trap();
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
asm("ud2");
#elif defined(SIGILL)
raise(SIGILL);
#endif
crashFallback();
}
} // namespace tst_QProcessCrash

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testExitCodes
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -13,7 +13,7 @@ static bool waitForDoneFileWritten(const QString &filePath, int msecs = 30000)
{
QDeadlineTimer t(msecs);
do {
QThread::msleep(250);
QThread::sleep(std::chrono::milliseconds{250});
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly))
continue;

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testForwardingHelper
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testProcessCrash
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -2,49 +2,12 @@
// Copyright (C) 2020 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#if __has_include(<sys/resource.h>)
# include <sys/resource.h>
# if defined(RLIMIT_CORE)
static bool disableCoreDumps()
{
// Unix: set our core dump limit to zero to request no dialogs.
if (struct rlimit rlim; getrlimit(RLIMIT_CORE, &rlim) == 0) {
rlim.rlim_cur = 0;
setrlimit(RLIMIT_CORE, &rlim);
}
return true;
}
static bool disabledCoreDumps = disableCoreDumps();
# endif // RLIMIT_CORE
#endif // <sys/resource.h>
void crashFallback(volatile int *ptr = nullptr)
{
*ptr = 0;
}
#if defined(_MSC_VER)
# include <intrin.h>
#include "../crasher.h"
using namespace tst_QProcessCrash;
int main()
{
# if defined(_M_IX86) || defined(_M_X64)
__ud2();
# endif
crashFallback();
NoCoreDumps disableCoreDumps;
crash();
return 0;
}
#elif defined(__MINGW32__)
int main()
{
asm("ud2");
crashFallback();
}
#else
# include <stdlib.h>
int main()
{
abort();
}
#endif

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testProcessDeadWhileReading
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testProcessEOF
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testProcessEcho
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testProcessEcho2
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testProcessEcho3
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -8,6 +8,7 @@
qt_internal_add_executable(testProcessEchoGui
GUI
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main_win.cpp
)

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testProcessEnvironment
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testProcessHang
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testProcessNormal
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testProcessOutput
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -3,12 +3,14 @@
qt_internal_add_executable(nospace
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)
qt_internal_add_executable(onespace
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)
@ -16,6 +18,7 @@ set_target_properties(onespace PROPERTIES OUTPUT_NAME "one space")
qt_internal_add_executable(twospaces
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testSetNamedPipeHandleState
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testSoftExit
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
)
qt_internal_extend_target(testSoftExit CONDITION WIN32

View File

@ -7,6 +7,7 @@
qt_internal_add_executable(testSpaceInName
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -0,0 +1,13 @@
# Copyright (C) 2023 Intel Corporation.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## testProcessNormal Binary:
#####################################################################
qt_internal_add_executable(testUnixProcessParameters
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
CORE_LIBRARY None
SOURCES
main.cpp
)

View File

@ -0,0 +1,85 @@
// Copyright (C) 2023 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <string_view>
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (argc < 2) {
printf("Usage: %s command [extra]\nSee source code for commands\n",
argv[0]);
return EXIT_FAILURE;
}
std::string_view cmd = argv[1];
errno = 0;
if (cmd.size() == 0) {
// just checking that we did get here
return EXIT_SUCCESS;
}
if (cmd == "reset-sighand") {
bool ok = true;
// confirm our signal block mask is empty
sigset_t set;
sigprocmask(SIG_SETMASK, nullptr, &set);
for (int signo = 1; signo < NSIG; ++signo) {
if (sigismember(&set, signo)) {
fprintf(stderr, "'%s' is blocked.\n", strsignal(signo));
ok = false;
}
}
// confirm SIGUSR1 was not ignored
struct sigaction action;
sigaction(SIGUSR1, nullptr, &action);
if (action.sa_handler != SIG_DFL) {
fprintf(stderr, "SIGUSR1 is SIG_IGN\n");
ok = false;
}
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
if (cmd == "ignore-sigpipe") {
// confirm SIGPIPE was ignored
struct sigaction action;
sigaction(SIGPIPE, nullptr, &action);
if (action.sa_handler == SIG_IGN)
return EXIT_SUCCESS;
fprintf(stderr, "SIGPIPE is SIG_DFL\n");
return EXIT_FAILURE;
}
if (cmd == "file-descriptors") {
int fd = atoi(argv[2]);
if (close(fd) < 0 && errno == EBADF)
return EXIT_SUCCESS;
fprintf(stderr, "%d is a valid file descriptor\n", fd);
return EXIT_FAILURE;
}
if (cmd == "file-descriptors2") {
int fd1 = atoi(argv[2]); // should be open
int fd2 = atoi(argv[3]); // should be closed
if (close(fd1) < 0)
fprintf(stderr, "%d was not a valid file descriptor\n", fd1);
if (close(fd2) == 0 || errno != EBADF)
fprintf(stderr, "%d is a valid file descriptor\n", fd2);
return EXIT_SUCCESS;
}
fprintf(stderr, "Unknown command \"%s\"", cmd.data());
return EXIT_FAILURE;
}

View File

@ -21,6 +21,7 @@
#include <qplatformdefs.h>
#ifdef Q_OS_UNIX
# include <private/qcore_unix_p.h>
# include <sys/wait.h>
#endif
#include <QtTest/private/qemulationdetector_p.h>
@ -111,7 +112,13 @@ private slots:
void createProcessArgumentsModifier();
#endif // Q_OS_WIN
#if defined(Q_OS_UNIX)
void setChildProcessModifier_data();
void setChildProcessModifier();
void throwInChildProcessModifier();
void unixProcessParameters_data();
void unixProcessParameters();
void unixProcessParametersAndChildModifier();
void unixProcessParametersOtherFileDescriptors();
#endif
void exitCodeTest();
void systemEnvironment();
@ -152,6 +159,7 @@ protected slots:
private:
qint64 bytesAvailable;
QTemporaryDir m_temporaryDir;
bool haveWorkingVFork = false;
};
void tst_QProcess::initTestCase()
@ -163,6 +171,12 @@ void tst_QProcess::initTestCase()
// chdir to our testdata path and execute helper apps relative to that.
QString testdata_dir = QFileInfo(QFINDTESTDATA("testProcessNormal")).absolutePath();
QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir));
#if defined(Q_OS_LINUX) && QT_CONFIG(forkfd_pidfd)
// see detect_clone_pidfd_support() in forkfd_linux.c for explanation
waitid(/*P_PIDFD*/ idtype_t(3), INT_MAX, NULL, WEXITED|WNOHANG);
haveWorkingVFork = (errno == EBADF);
#endif
}
void tst_QProcess::cleanupTestCase()
@ -1445,8 +1459,16 @@ static void childProcessModifier(int fd)
QT_CLOSE(fd);
}
void tst_QProcess::setChildProcessModifier_data()
{
QTest::addColumn<bool>("detached");
QTest::newRow("normal") << false;
QTest::newRow("detached") << true;
}
void tst_QProcess::setChildProcessModifier()
{
QFETCH(bool, detached);
int pipes[2] = { -1 , -1 };
QVERIFY(qt_safe_pipe(pipes) == 0);
@ -1454,20 +1476,215 @@ void tst_QProcess::setChildProcessModifier()
process.setChildProcessModifier([pipes]() {
::childProcessModifier(pipes[1]);
});
process.start("testProcessNormal/testProcessNormal");
if (process.state() != QProcess::Starting)
QCOMPARE(process.state(), QProcess::Running);
QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString()));
process.setProgram("testProcessNormal/testProcessNormal");
if (detached) {
process.startDetached();
} else {
process.start("testProcessNormal/testProcessNormal");
if (process.state() != QProcess::Starting)
QCOMPARE(process.state(), QProcess::Running);
QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString()));
QVERIFY2(process.waitForFinished(5000), qPrintable(process.errorString()));
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 0);
}
char buf[sizeof messageFromChildProcess] = {};
qt_safe_close(pipes[1]);
QCOMPARE(qt_safe_read(pipes[0], buf, sizeof(buf)), qint64(sizeof(messageFromChildProcess)) - 1);
QCOMPARE(buf, messageFromChildProcess);
qt_safe_close(pipes[0]);
}
QVERIFY2(process.waitForFinished(5000), qPrintable(process.errorString()));
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
void tst_QProcess::throwInChildProcessModifier()
{
#ifndef __cpp_exceptions
Q_SKIP("Exceptions disabled.");
#else
QProcess process;
process.setChildProcessModifier([]() {
throw 42;
});
process.setProgram("testProcessNormal/testProcessNormal");
process.start();
QVERIFY(!process.waitForStarted(5000));
QCOMPARE(process.state(), QProcess::NotRunning);
QCOMPARE(process.error(), QProcess::FailedToStart);
QVERIFY2(process.errorString().contains("childProcessModifier"),
qPrintable(process.errorString()));
// try again, to ensure QProcess internal state wasn't corrupted
process.start();
QVERIFY(!process.waitForStarted(5000));
QCOMPARE(process.state(), QProcess::NotRunning);
QCOMPARE(process.error(), QProcess::FailedToStart);
QVERIFY2(process.errorString().contains("childProcessModifier"),
qPrintable(process.errorString()));
#endif
}
void tst_QProcess::unixProcessParameters_data()
{
QTest::addColumn<QProcess::UnixProcessParameters>("params");
QTest::addColumn<QString>("cmd");
QTest::newRow("defaults") << QProcess::UnixProcessParameters{} << QString();
auto addRow = [](const char *cmd, QProcess::UnixProcessFlags flags) {
QProcess::UnixProcessParameters params = {};
params.flags = flags;
QTest::addRow("%s", cmd) << params << cmd;
};
using P = QProcess::UnixProcessFlag;
addRow("reset-sighand", P::ResetSignalHandlers);
addRow("ignore-sigpipe", P::IgnoreSigPipe);
addRow("file-descriptors", P::CloseFileDescriptors);
}
void tst_QProcess::unixProcessParameters()
{
QFETCH(QProcess::UnixProcessParameters, params);
QFETCH(QString, cmd);
// set up a few things
struct Scope {
int devnull;
struct sigaction old_sigusr1, old_sigpipe;
Scope()
{
int fd = open("/dev/null", O_RDONLY);
devnull = fcntl(fd, F_DUPFD, 100);
close(fd);
// we ignore SIGUSR1 and reset SIGPIPE to Terminate
struct sigaction act = {};
sigemptyset(&act.sa_mask);
act.sa_handler = SIG_IGN;
sigaction(SIGUSR1, &act, &old_sigusr1);
act.sa_handler = SIG_DFL;
sigaction(SIGPIPE, &act, &old_sigpipe);
// and we block SIGUSR2
sigset_t *set = &act.sa_mask; // reuse this sigset_t
sigaddset(set, SIGUSR2);
sigprocmask(SIG_BLOCK, set, nullptr);
}
~Scope()
{
if (devnull != -1)
dismiss();
}
void dismiss()
{
close(devnull);
sigaction(SIGUSR1, &old_sigusr1, nullptr);
sigaction(SIGPIPE, &old_sigpipe, nullptr);
devnull = -1;
sigset_t *set = &old_sigusr1.sa_mask; // reuse this sigset_t
sigaddset(set, SIGUSR2);
sigprocmask(SIG_BLOCK, set, nullptr);
}
} scope;
QProcess process;
process.setUnixProcessParameters(params);
process.setStandardInputFile(QProcess::nullDevice()); // so we can't mess with SIGPIPE
process.setProgram("testUnixProcessParameters/testUnixProcessParameters");
process.setArguments({ cmd, QString::number(scope.devnull) });
process.start();
QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString()));
QVERIFY(process.waitForFinished(5000));
const QString stdErr = process.readAllStandardError();
QCOMPARE(stdErr, QString());
QCOMPARE(process.readAll(), QString());
QCOMPARE(process.exitCode(), 0);
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
}
void tst_QProcess::unixProcessParametersAndChildModifier()
{
static constexpr char message[] = "Message from the handler function\n";
static_assert(std::char_traits<char>::length(message) <= PIPE_BUF);
QProcess process;
QAtomicInt vforkControl;
int pipes[2];
QVERIFY2(pipe(pipes) == 0, qPrintable(qt_error_string()));
auto pipeGuard0 = qScopeGuard([=] { close(pipes[0]); });
{
auto pipeGuard1 = qScopeGuard([=] { close(pipes[1]); });
// verify that our modifier runs before the parameters are applied
process.setChildProcessModifier([=, &vforkControl] {
write(pipes[1], message, strlen(message));
vforkControl.storeRelaxed(1);
});
auto flags = QProcess::UnixProcessFlag::CloseFileDescriptors |
QProcess::UnixProcessFlag::UseVFork;
process.setUnixProcessParameters({ flags });
process.setProgram("testUnixProcessParameters/testUnixProcessParameters");
process.setArguments({ "file-descriptors", QString::number(pipes[1]) });
process.start();
QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString()));
} // closes the writing end of the pipe
QVERIFY(process.waitForFinished(5000));
QCOMPARE(process.readAllStandardError(), QString());
QCOMPARE(process.readAll(), QString());
char buf[2 * sizeof(message)];
int r = read(pipes[0], buf, sizeof(buf));
QVERIFY2(r >= 0, qPrintable(qt_error_string()));
QCOMPARE(QByteArrayView(buf, r), message);
if (haveWorkingVFork)
QVERIFY2(vforkControl.loadRelaxed(), "QProcess doesn't appear to have used vfork()");
}
void tst_QProcess::unixProcessParametersOtherFileDescriptors()
{
constexpr int TargetFileDescriptor = 3;
int pipes[2];
int fd1 = open("/dev/null", O_RDONLY);
int devnull = fcntl(fd1, F_DUPFD, 100); // instead of F_DUPFD_CLOEXEC
qt_safe_pipe(pipes); // implied O_CLOEXEC
close(fd1);
auto closeFds = qScopeGuard([&] {
close(devnull);
close(pipes[0]);
// we'll close pipe[1] before any QCOMPARE
});
QProcess process;
QProcess::UnixProcessParameters params;
params.flags = QProcess::UnixProcessFlag::CloseFileDescriptors
| QProcess::UnixProcessFlag::UseVFork;
params.lowestFileDescriptorToClose = 4;
process.setUnixProcessParameters(params);
process.setChildProcessModifier([devnull, pipes]() {
if (dup2(devnull, TargetFileDescriptor) == TargetFileDescriptor)
return;
write(pipes[1], &errno, sizeof(errno));
_exit(255);
});
process.setProgram("testUnixProcessParameters/testUnixProcessParameters");
process.setArguments({ "file-descriptors2", QString::number(TargetFileDescriptor),
QString::number(devnull) });
process.start();
close(pipes[1]);
if (int duperror; read(pipes[0], &duperror, sizeof(duperror)) == sizeof(duperror))
QFAIL(QByteArray("dup2 failed: ") + strerror(duperror));
QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString()));
QVERIFY(process.waitForFinished(5000));
QCOMPARE(process.readAllStandardError(), QString());
QCOMPARE(process.readAll(), QString());
QCOMPARE(process.exitCode(), 0);
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
}
#endif
@ -1500,7 +1717,7 @@ void tst_QProcess::failToStart()
// to many processes here will cause test failures later on.
#if defined Q_OS_HPUX
const int attempts = 15;
#elif defined Q_OS_MAC
#elif defined Q_OS_DARWIN
const int attempts = 15;
#else
const int attempts = 50;
@ -2362,7 +2579,7 @@ public:
public slots:
void block()
{
QThread::sleep(1);
QThread::sleep(std::chrono::seconds{1});
}
};