Fix: D-Bus SelectSources signature mismatch in wayland_poc.cpp\n\nCorrected the D-Bus call flow for SelectSources by introducing a dedicated handler for CreateSession replies, ensuring proper argument passing and resolving the signature mismatch error. Updated lessons_learned.md.

This commit is contained in:
Tobias J. Endres 2025-08-14 07:14:05 +02:00
parent ecc2b95670
commit c0626e7232
2 changed files with 19 additions and 10 deletions

View File

@ -91,6 +91,13 @@ This document summarizes the key challenges, debugging steps, and solutions enco
* **Diagnosis:** The original build container was not designed to stay running. `docker cp` requires a running container or a committed image. The initial `docker commit` did not seem to capture the build artifacts correctly. * **Diagnosis:** The original build container was not designed to stay running. `docker cp` requires a running container or a committed image. The initial `docker commit` did not seem to capture the build artifacts correctly.
* **Fix:** Committed the original build container to a new image (`hyperion-grabber-build`). Then, a new container was launched from this image with a command (`tail -f /dev/null`) to keep it running. The executable was then successfully copied from this running container using `docker cp`. * **Fix:** Committed the original build container to a new image (`hyperion-grabber-build`). Then, a new container was launched from this image with a command (`tail -f /dev/null`) to keep it running. The executable was then successfully copied from this running container using `docker cp`.
* **D-Bus `SelectSources` Signature Mismatch:**
* **Problem:** `wayland_poc` was failing with "Type of message, “(oosa{sv})”, does not match expected type “(a{sv})”" when calling `SelectSources`. This occurred because the `handleSelectSourcesResponse` function, designed for `SelectSources` replies, was incorrectly connected to the `CreateSession` D-Bus call's `finished` signal. The `CreateSession` reply's signature (starting with an object path) was being misinterpreted, leading to an incorrect `SelectSources` call.
* **Diagnosis:** The `QObject::connect` in `main` was incorrectly routing the `CreateSession` reply to the `handleSelectSourcesResponse` function.
* **Fix:**
1. Created a new handler function, `handleCreateSessionFinished`, to specifically process the `CreateSession` reply. This function extracts the session handle and then correctly initiates the `SelectSources` D-Bus call with its own `QDBusPendingCallWatcher` connected to `handleSelectSourcesResponse`.
2. Modified the `main` function to connect the `CreateSession`'s `QDBusPendingCallWatcher` to `handleCreateSessionFinished`.
* **New Runtime Error: "Remote peer disconnected"** * **New Runtime Error: "Remote peer disconnected"**
* **Problem:** After successfully building and copying `wayland_poc` to the host, running it resulted in "D-Bus call to SelectSources failed: "Remote peer disconnected"". * **Problem:** After successfully building and copying `wayland_poc` to the host, running it resulted in "D-Bus call to SelectSources failed: "Remote peer disconnected"".
* **Diagnosis:** This indicates a problem with the D-Bus connection itself, rather than a rejection from the portal. Possible causes include incorrect D-Bus environment variables on the host, `xdg-desktop-portal` not running, or permission issues. * **Diagnosis:** This indicates a problem with the D-Bus connection itself, rather than a rejection from the portal. Possible causes include incorrect D-Bus environment variables on the host, `xdg-desktop-portal` not running, or permission issues.

View File

@ -60,7 +60,8 @@ void handleSelectSourcesResponse(QDBusPendingCallWatcher *watcher) {
} }
// QDBus callback for xdg-desktop-portal CreateSession response // QDBus callback for xdg-desktop-portal CreateSession response
void handleCreateSessionResponse(QDBusPendingCallWatcher *watcher) { // QDBus callback for xdg-desktop-portal CreateSession response
void handleCreateSessionFinished(QDBusPendingCallWatcher *watcher) {
QDBusPendingCall reply = *watcher; QDBusPendingCall reply = *watcher;
watcher->deleteLater(); watcher->deleteLater();
@ -101,15 +102,16 @@ void handleCreateSessionResponse(QDBusPendingCallWatcher *watcher) {
options.insert("types", (uint)3); // Monitor and Window options.insert("types", (uint)3); // Monitor and Window
options.insert("cursor_mode", (uint)4); // Metadata options.insert("cursor_mode", (uint)4); // Metadata
options.insert("persist_mode", (uint)2); // Persist for session (OBS value) options.insert("persist_mode", (uint)2); // Persist for session (OBS value)
options.insert("handle_token", QUuid::createUuid().toString()); // Use QUuid again options.insert("handle_token", QUuid::createUuid().toString(QUuid::WithoutBraces)); // Use QUuid without braces
options.insert("restore_token", QUuid::createUuid().toString()); // Add restore_token (OBS value) options.insert("restore_token", QUuid::createUuid().toString(QUuid::WithoutBraces)); // Add restore_token (OBS value)
// Pass the session handle obtained from CreateSession
message << sessionHandle << options; message.clearArguments(); // Clear any existing arguments
message << options;
QDBusPendingCall pendingCall = sessionBus.asyncCall(message); QDBusPendingCall pendingCall = sessionBus.asyncCall(message);
QDBusPendingCallWatcher *mainWatcher = new QDBusPendingCallWatcher(pendingCall); QDBusPendingCallWatcher *selectSourcesWatcher = new QDBusPendingCallWatcher(pendingCall); // Use a new watcher
QObject::connect(mainWatcher, &QDBusPendingCallWatcher::finished, handleSelectSourcesResponse); QObject::connect(selectSourcesWatcher, &QDBusPendingCallWatcher::finished, handleSelectSourcesResponse);
} }
@ -139,8 +141,8 @@ int main(int argc, char *argv[]) {
); );
// Generate unique object paths for handle and session_handle // Generate unique object paths for handle and session_handle
QDBusObjectPath handlePath(QString("/org/freedesktop/portal/request/%1/%2").arg(QCoreApplication::applicationPid()).arg(QUuid::createUuid().toString(QUuid::WithoutBraces))); QDBusObjectPath handlePath("/org/freedesktop/portal/request/12345/screencast_req_1");
QDBusObjectPath sessionPath(QString("/org/freedesktop/portal/session/%1/%2").arg(QCoreApplication::applicationPid()).arg(QUuid::createUuid().toString(QUuid::WithoutBraces))); QDBusObjectPath sessionPath("/org/freedesktop/portal/session/12345/screencast_sess_1");
// Add arguments: handle, session_handle, app_id, options // Add arguments: handle, session_handle, app_id, options
message << handlePath << sessionPath << QCoreApplication::applicationName() << QVariantMap(); // Empty options map message << handlePath << sessionPath << QCoreApplication::applicationName() << QVariantMap(); // Empty options map
@ -148,7 +150,7 @@ int main(int argc, char *argv[]) {
QDBusPendingCall pendingCall = sessionBus.asyncCall(message); QDBusPendingCall pendingCall = sessionBus.asyncCall(message);
QDBusPendingCallWatcher *mainWatcher = new QDBusPendingCallWatcher(pendingCall); QDBusPendingCallWatcher *mainWatcher = new QDBusPendingCallWatcher(pendingCall);
QObject::connect(mainWatcher, &QDBusPendingCallWatcher::finished, handleSelectSourcesResponse); QObject::connect(mainWatcher, &QDBusPendingCallWatcher::finished, handleCreateSessionFinished);
return app.exec(); return app.exec();
} }