fix: comprehensive boot warnings and exceptions — fixable silenced, unfixable diagnosed

Build system (5 gaps hardened):
- COOKBOOK_OFFLINE defaults to true (fork-mode)
- normalize_patch handles diff -ruN format
- New 'repo validate-patches' command (25/25 relibc patches)
- 14 patched Qt/Wayland/display recipes added to protected list
- relibc archive regenerated with current patch chain

Boot fixes (fixable):
- Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset)
- D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped)
- redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped)
- daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch)
- udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async)
- relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs
- greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait)
- greeter-ui: built and linked (header guard unification, sem_compat stubs removed)
- mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps
- greeter config: removed stale keymapd dependency from display/greeter services
- prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified

Unfixable (diagnosed, upstream):
- i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort
- kded6/greeter-ui: page fault 0x8 — Qt library null deref
- Thread panics fd != -1 — Rust std library on Redox
- DHCP timeout / eth0 MAC — QEMU user-mode networking
- hwrngd/thermald — no hardware RNG/thermal in VM
- live preload allocation — BIOS memory fragmentation, continues on demand
This commit is contained in:
2026-05-05 20:20:37 +01:00
parent a5f97b6632
commit f31522130f
81834 changed files with 11051982 additions and 108 deletions
@@ -0,0 +1,26 @@
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qml LANGUAGES CXX)
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
data/*)
list(APPEND test_data ${test_data_glob})
qt_internal_add_test(tst_qml
SOURCES
tst_qml.cpp
DEFINES
QT_QMLTEST_DIR="${CMAKE_CURRENT_SOURCE_DIR}"
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
LIBRARIES
Qt::QuickTestUtilsPrivate
Qt::Gui
Qt::GuiPrivate
)
@@ -0,0 +1,5 @@
import QtQml
QtObject {
Component.onCompleted: Qt.quit()
}
@@ -0,0 +1,28 @@
import QtQuick
Rectangle {
id: rect
color: "green"
Timer {
id: exitTimer
running: false
onTriggered: Qt.quit()
}
Timer {
id: resizeTimer
running: false
onTriggered: {
rect.width = 100
rect.height = 50
exitTimer.start()
}
}
Window.onHeightChanged: {
if (rect.Window.width > 0)
console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
resizeTimer.start()
}
}
@@ -0,0 +1,19 @@
import QtQuick
Rectangle {
id: rect
color: "blue"
width: 200; height: 150
Timer {
id: exitTimer
running: false
onTriggered: Qt.quit()
}
Window.onHeightChanged: {
if (rect.Window.width > 0)
console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
exitTimer.restart()
}
}
@@ -0,0 +1,18 @@
import QtQuick
Rectangle {
id: rect
color: "green"
Timer {
id: exitTimer
running: false
onTriggered: Qt.quit()
}
Window.onHeightChanged: {
if (rect.Window.width > 0)
console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
exitTimer.restart()
}
}
@@ -0,0 +1,215 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qprocess.h>
#include <QtCore/qloggingcategory.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qpa/qplatformintegration.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QTemporaryFile>
Q_LOGGING_CATEGORY(lcQml, "qt.qml.tests");
class tst_qml : public QQmlDataTest
{
Q_OBJECT
public:
tst_qml() : QQmlDataTest(QT_QMLTEST_DATADIR) {}
private slots:
void initTestCase() override;
void nonWindow();
void itemAndWindowGeometry_data();
void itemAndWindowGeometry();
void extraPositionalArguments();
private:
QString qmlPath;
};
void tst_qml::initTestCase()
{
QQmlDataTest::initTestCase();
qmlPath = QLibraryInfo::path(QLibraryInfo::BinariesPath);
#if defined(Q_OS_WIN)
qmlPath += QLatin1String("/qml.exe");
#else
qmlPath += QLatin1String("/qml");
#endif
QVERIFY(QFileInfo(qmlPath).exists());
}
void tst_qml::nonWindow()
{
QProcess qml;
qml.start(qmlPath, { testFile("nonWindow.qml") });
QVERIFY(qml.waitForFinished());
QCOMPARE(qml.exitCode(), 0); // Should not exit with code 2
}
void tst_qml::itemAndWindowGeometry_data()
{
QTest::addColumn<QString>("config");
QTest::addColumn<QString>("geometry");
QTest::addColumn<QString>("qmlfile");
QTest::addColumn<QSize>("expectedWindowSize");
QTest::addColumn<QSize>("expectedContentSize");
const QString none; // empty string
auto sizeOrInvalid = [](int w, int h) {
static const bool wm = QGuiApplicationPrivate::platformIntegration()->
hasCapability(QPlatformIntegration::WindowManagement);
return wm ? QSize(w, h) : QSize();
};
QTest::newRow("default: unsized")
<< none << none << "unsizedItem.qml"
<< QSize() << QSize(); // default size depends on window system
QTest::newRow("default: unsized with geometry")
<< none << "100x100+50+50" << "unsizedItem.qml"
<< sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
QTest::newRow("resizeToItem: unsized")
<< "resizeToItem" << none << "unsizedItem.qml"
<< QSize() << QSize(0, 0);
QTest::newRow("resizeToItem: unsized with geometry")
<< "resizeToItem" << "100x100+50+50" << "unsizedItem.qml"
<< sizeOrInvalid(100, 100) << QSize(0, 0);
QTest::newRow("default: sized")
<< none << none << "sizedItem.qml"
<< QSize() << QSize();
QTest::newRow("default: sized with geometry")
<< none << "100x100+50+50" << "sizedItem.qml"
<< sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
QTest::newRow("resizeToItem: sized")
<< "resizeToItem" << none << "sizedItem.qml"
<< sizeOrInvalid(200, 150) << sizeOrInvalid(200, 150);
QTest::newRow("resizeToItem: sized with geometry")
<< "resizeToItem" << "320x240+50+50" << "sizedItem.qml"
<< sizeOrInvalid(320, 240) << QSize(200, 150);
QTest::newRow("default: resizing")
<< none << none << "resizeItem.qml"
<< QSize() << QSize();
QTest::newRow("default: resizing with geometry")
<< none << "100x100+50+50" << "resizeItem.qml"
<< sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
QTest::newRow("resizeToItem: resizing")
<< "resizeToItem" << none << "resizeItem.qml"
<< sizeOrInvalid(100, 50) << sizeOrInvalid(100, 50);
QTest::newRow("resizeToItem: resizing with geometry")
<< "resizeToItem" << "320x240+50+50" << "resizeItem.qml"
<< sizeOrInvalid(100, 50) << sizeOrInvalid(100, 50);
}
/*
- A root Item will get put into a Window depending on config (implementations in
tools/qml/ResizeItemToWindow.qml and ResizeWindowToItem.qml).
- The window system will enforce a minimum size.
- In the default configuration, the root Item should then get resized to fit
(QTBUG-114068 / QTBUG-116753).
- In resizeToItem configuration, if the item width/height are not set, the window would
try to be 0x0, but the window system won't allow it.
- This also tests the `--qwindowgeometry` argument: with the default config, the
item should be resized to fit, but not with `-c resizeToItem`.
*/
void tst_qml::itemAndWindowGeometry()
{
#ifdef Q_OS_WIN
QSKIP("console.info does not go to stderr on Windows.");
#endif
QFETCH(QString, config);
QFETCH(QString, geometry);
QFETCH(QString, qmlfile);
QFETCH(QSize, expectedWindowSize);
QFETCH(QSize, expectedContentSize);
QStringList args;
if (!config.isEmpty())
args << "-c" << config;
if (!geometry.isEmpty())
args << "--qwindowgeometry" << geometry;
args << testFile(qmlfile);
QProcess qml;
qml.start(qmlPath, args);
QVERIFY(qml.waitForFinished());
const QByteArray output = qml.readAllStandardOutput();
const QByteArray error = qml.readAllStandardError();
const auto guard = qScopeGuard([&]() {
if (!QTest::currentTestFailed())
return;
qWarning() << "stdout:" << output;
qWarning() << "stderr:" << error;
});
QCOMPARE(qml.exitStatus(), QProcess::NormalExit);
const auto sizeLineIndex = error.lastIndexOf("window");
QCOMPARE_GE(sizeLineIndex, 0);
const auto newlineIndex = error.indexOf('\n', sizeLineIndex);
QCOMPARE_GT(newlineIndex, sizeLineIndex);
// expect a line like "window 120 120 content 120 120"
const auto sizes = error.sliced(sizeLineIndex, newlineIndex - sizeLineIndex).split(' ');
QCOMPARE_GE(sizes.size(), 6);
QCOMPARE(sizes[0], "window");
QCOMPARE(sizes[3], "content");
const QSize windowSize(sizes[1].toInt(), sizes[2].toInt());
const QSize contentSize(sizes[4].toInt(), sizes[5].toInt());
qCDebug(lcQml) << sizes
<< "window" << windowSize << "expect" << expectedWindowSize
<< "content" << contentSize << "expect" << expectedContentSize;
QVERIFY(!windowSize.isEmpty());
if (config != "resizeToItem") {
// default config:
// ResizeItemToWindow.qml should have resized the item to its window
QCOMPARE(contentSize, windowSize);
}
// windowSize can be off-by-one on hidpi (e.g. QT_SCALE_FACTOR=2 on xcb);
// perhaps that's a bug somewhere, but so far we aren't testing hidpi on CI
if (expectedWindowSize.isValid())
QCOMPARE(windowSize, expectedWindowSize);
if (expectedContentSize.isValid())
QCOMPARE(contentSize, expectedContentSize);
}
void tst_qml::extraPositionalArguments()
{
QProcess qml;
QStringList args;
QTemporaryFile f;
QVERIFY(f.open());
QVERIFY(f.write(R"(import QtQml
QtObject {
Component.onCompleted: {
let s = ""
for (let i = 2; i < Qt.application.arguments.length; ++i)
s += Qt.application.arguments[i].substring(1)
console.log(s)
Qt.quit()
}
}
)"));
f.flush();
args << f.fileName();
args << "--";
for (char c = 'a'; c <= 'z'; ++c)
args << u'-' + QString(c);
qml.start(qmlPath, args);
QVERIFY(qml.waitForFinished());
QVERIFY(qml.exitStatus() == QProcess::NormalExit && qml.exitCode() == 0);
QVERIFY(qml.readAllStandardError().contains("abcdefghijklmnopqrstuvwxyz"));
}
QTEST_MAIN(tst_qml)
#include <tst_qml.moc>