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;
}

Reply via email to