On Sun Nov 13, 2022 at 08:37:55PM +0100, Rafael Sadowski wrote:
> I don't know if this has worked in the past, but when debugging some Qt
> applications I saw the following debug messages:
>
> $ gwenview
> qt.qpa.xcb: Has MIT-SHM : true
> qt.qpa.xcb: Has MIT-SHM FD : true
> qt.qpa.xcb: xcb_shm_attach() failed
> qt.qpa.xcb: failed to create System V shared memory segment (remote X11
> connection?), disabling SHM
> qt.qpa.xcb: Using XInput version 2.2
> qt.qpa.screen: Output DP-1 is not connected
> qt.qpa.screen: Output HDMI-1 is not connected
>
> The code that fails is here. xcb_shm_attach_checked and/or
> xcb_request_check failed with all my Qt applications.
>
> pobj/qtbase-5.15.6/qtbase-everywhere-src-5.15.6/src/plugins/platforms/xcb/qxcbbackingstore.cpp
>
> bool QXcbBackingStoreImage::createSystemVShmSegment(xcb_connection_t *c,
> size_t segmentSize,
> xcb_shm_segment_info_t
> *shmInfo)
> {
> const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0x1C0);
> if (id == -1) {
> qCWarning(lcQpaXcb, "shmget() failed (%d: %s) for size %zu", errno,
> strerror(errno), segmentSize);
> return false;
> }
>
> void *addr = shmat(id, nullptr, 0);
> if (addr == (void *)-1) {
> qCWarning(lcQpaXcb, "shmat() failed (%d: %s) for id %d", errno,
> strerror(errno), id);
> return false;
> }
>
> if (shmctl(id, IPC_RMID, nullptr) == -1)
> qCWarning(lcQpaXcb, "Error while marking the shared memory segment to
> be destroyed");
>
> const auto seg = xcb_generate_id(c);
> auto cookie = xcb_shm_attach_checked(c, seg, id, false);
> auto *error = xcb_request_check(c, cookie);
> if (error) {
> qCWarning(lcQpaXcb(), "xcb_shm_attach() failed");
> free(error);
> if (shmdt(addr) == -1)
> qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p", errno,
> strerror(errno), addr);
> return false;
>
>
> If you want to test it run any Qt application with
> QT_LOGGING_RULES="qt.qpa.xcb.debug=true" exported.
>
> Should SHM with XCB generally work on OpenBSD?
>
> Rafael
>
Okay I tried to isolate that issue form Qt and unfortunately I can
reproduce the same issue.
The following code only works with "DISPLAY:0" and xcb_connect. Which is
wired, isn't?
- xcb_connect(3):
- display_name = "DISPLAY:0" - works
- display_name = ":0" fails with xcb_shm_attach_checked
- display_name = NULL fails with xcb_shm_attach_checked
- XOpenDisplay(3):
- display_name = "DISPLAY:0" - segmentation fault
- display_name = ":0" fails with xcb_shm_attach_checked
- display_name = NULL fails with xcb_shm_attach_checked
Qt use XOpenDisplay(3) to connect to the XServer. Unfortunately, I can't
find a solution with XOpenDisplay(3) which works with SHM. Someone has
an idea or can confirm my issue?
Here is my "small" test case:
// cc -O2 -pipe -std=c99 -I/usr/X11R6/include/xcb -I/usr/X11R6/include
-L/usr/X11R6/lib \
// -lxcb-shm -lxcb -lX11-xcb -lX11 xcb_shm_attach.c
#include <xcb.h>
#include <xcb/shm.h>
#include <xcb/xcb_image.h>
#include <xcb/render.h>
#include <xcb/xcb_renderutil.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
#include <X11/Xlibint.h>
#include <X11/Xutil.h>
int main(int argc, char *argv[]) {
// create connection to X11 server
/**
* displayname = "DISPLAY:0" work with xcb_shm_attach_checked
* displayname = ":0" NOT work with xcb_shm_attach_checked
* displayname = NULL NOT work with xcb_shm_attach_checked
*/
/*
int screen = 0;
xcb_connection_t* c = xcb_connect("DISPLAY:0", &screen); // is the only one
that works with xcb_shm_attach_checked
if(c == NULL) {
printf("xcb_connect");
return -1;
}
*/
/**
* displayname = "DISPLAY:0" segmentation fault
* displayname = ":0" NOT work with xcb_shm_attach_checked
* displayname = NULL NOT work with xcb_shm_attach_checked
*/
Display *dpy = XOpenDisplay(NULL);
xcb_connection_t* c = XGetXCBConnection(dpy);
struct xcb_shm_segment_info_t *shmInfo;
size_t segmentSize = 1800;
const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600);
if (id == -1) {
printf("shmget");
return -1;
}
void *addr = shmat(id, NULL, 0);
if (addr == (void *)-1) {
printf("shmat");
return -1;
}
if (shmctl(id, IPC_RMID, NULL) == -1) {
printf("shmctl");
return -1;
}
const uint32_t seg = xcb_generate_id(c);
xcb_void_cookie_t cookie = xcb_shm_attach_checked(c, seg, id, 1);
xcb_generic_error_t* error = xcb_request_check(c, cookie);
if (error) {
fprintf(stderr, "xcb_shm_attach_checked Error %d\n", error->error_code);
free(error);
if (shmdt(addr) == -1) {
printf("xcb_request_check 2");
return -1;
}
return -1;
} else if (!shmInfo) {
printf("xcb_shm_detach\n");
xcb_shm_detach(c, seg);
}
if (shmInfo) {
shmInfo->shmseg = seg;
shmInfo->shmid = id;
}
printf("worked");
return 0;
}