c++raspberry-pisdl-2hdmi

SDL2 without X show 'Segmentation fault' if no HDMI device connected


I want to make very simple TV panel tester. With this answer about SDL2 without X I was able to prepare such tester with Raspberry Pi Zero and it works very well. While running I can switch just cable between TVs' and I'm having very fast green screen on tested TV. However when I run program without connected any device on HDMI, I have Segmentation fault.

This is code:

#include <SDL.h>
#include <iostream>

int main( int argc, char** argv )
{

    if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
    {
        std::cerr << "SDL_Init(): " << SDL_GetError() << '\n';
        return EXIT_FAILURE;
    }

    SDL_Window* window = SDL_CreateWindow
        (
        "SDL2",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        1920, 1080,
        SDL_WINDOW_SHOWN
        );
    if( nullptr == window )
    {
        std::cerr << "SDL_CreateWindow(): " << SDL_GetError() << '\n';
        return EXIT_FAILURE;
    }

    SDL_Renderer* renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
    if( nullptr == renderer )
    {
        std::cerr << "SDL_CreateRenderer(): " << SDL_GetError() << '\n';
        return EXIT_FAILURE;
    }

    bool running = true;
    while( running )
    {
        SDL_Event ev;
        while( SDL_PollEvent( &ev ))
        {
            if( ev.type == SDL_QUIT )
            {
                running = false;
            }
        }

        SDL_SetRenderDrawColor( renderer, 0x00, 0xff, 0x00, SDL_ALPHA_OPAQUE );
        SDL_RenderClear( renderer );
        SDL_RenderPresent( renderer );
    }

    SDL_DestroyRenderer( renderer );
    SDL_DestroyWindow( window );
    SDL_Quit();
    return 0;
}

This is the end of strace this program:

close(5)                                = 0
openat(AT_FDCWD, "/usr/share/drirc.d/00-mesa-defaults.conf", O_RDONLY|O_LARGEFILE) = 5
read(5, "<?xml version=\"1.0\" standalone=\""..., 4096) = 4096
getrandom("\x26\x27\xac\x36", 4, GRND_NONBLOCK) = 4
read(5, ">\n\n        <application name=\"Un"..., 4096) = 4096
read(5, "_glsl_abs_sqrt\" value=\"true\" />\n"..., 4096) = 4096
read(5, "ation>\n\n        <application nam"..., 4096) = 4096
read(5, "daptive_sync\" value=\"false\" />\n "..., 4096) = 4096
read(5, "ation>\n        <application name"..., 4096) = 4096
read(5, "executable=\"dota2\">\n            "..., 4096) = 1062
read(5, "", 4096)                       = 0
close(5)                                = 0
openat(AT_FDCWD, "/etc/drirc", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/pi/.drirc", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
ioctl(4, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb98e0) = 0
fcntl64(4, F_DUPFD_CLOEXEC, 3)          = 5
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_GET_CAP, 0xbecb9860) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb9898) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb98a8) = 0
gettimeofday({tv_sec=1582731761, tv_usec=164921}, NULL) = 0
openat(AT_FDCWD, "/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC) = 6
read(6, "0\n", 8192)                    = 2
close(6)                                = 0
openat(AT_FDCWD, "/proc/self/auxv", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 6
read(6, "\20\0\0\0\326\201\0\0", 8)     = 8
close(6)                                = 0
futex(0xb5f4e3d0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
ioctl(5, DRM_IOCTL_TEGRA_GET_SYNCPT_BASE or DRM_IOCTL_VC4_GET_TILING, 0xbecb9860) = -1 ENOENT (No such file or directory)
ioctl(3, DRM_IOCTL_GET_CAP, 0xbecb9910) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb8cf0) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb8cf0) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb8cf0) = 0
ioctl(5, DRM_IOCTL_AMDGPU_GEM_WAIT_IDLE or DRM_IOCTL_EXYNOS_VIDI_CONNECTION or DRM_IOCTL_TEGRA_GET_SYNCPT or DRM_IOCTL_VC4_GET_PARAM or DRM_IOCTL_VIA_DMA_INIT, 0xbecb8cf0) = 0
ioctl(3, DRM_IOCTL_MODE_GETRESOURCES, 0xbecba340) = 0
ioctl(3, DRM_IOCTL_MODE_GETRESOURCES, 0xbecba340) = 0
ioctl(3, DRM_IOCTL_MODE_GETCONNECTOR, 0xbecba2f0) = 0
ioctl(3, DRM_IOCTL_MODE_GETCONNECTOR, 0xbecba2f0) = 0
ioctl(3, DRM_IOCTL_MODE_GETCONNECTOR, 0xbecba2f0) = 0
ioctl(3, DRM_IOCTL_MODE_GETCONNECTOR, 0xbecba2f0) = 0
close(5)                                = 0
close(4)                                = 0
munmap(0xb50af000, 17353000)            = 0
munmap(0xb14ea000, 115624)              = 0
munmap(0xb14cf000, 106672)              = 0
munmap(0xb14a5000, 168220)              = 0
munmap(0xb148d000, 94536)               = 0
munmap(0xb1476000, 90356)               = 0
close(3)                                = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x4} ---
+++ killed by SIGSEGV +++
Segmentation fault

And this is config.txt hdmi_ and display related part:

framebuffer_width=1920
framebuffer_height=1080
hdmi_force_hotplug=1
hdmi_ignore_edid=0xa5000080
hdmi_edid_file=1
hdmi_ignore_edid_audio=1
hdmi_force_edid_3d=1
hdmi_ignore_cec_init=1
hdmi_ignore_cec=1
hdmi_pixel_encoding=2
hdmi_blanking=0
edid_content_type=0
hdmi_group=1
hdmi_mode=16
hdmi_force_mode=1
dtoverlay=vc4-kms-v3d

How can I fix this problem?

Is there something I can run as dummy HDMI output before first device is connected?

Because I want to make this tester as headless autostarting device and because it will be turned on before any HDMI output will be connected (as booting rPi-Zero is slow - even minimalistic version).

[EDIT]

Output from full version of sample app:

Testing video drivers...
SDL_VIDEODRIVER available: x11 KMSDRM RPI dummy
SDL_VIDEODRIVER usable   : KMSDRM
SDL_VIDEODRIVER selected : KMSDRM
SDL_RENDER_DRIVER available: opengles2 opengles software
SDL_RENDER_DRIVER selected : opengles2

This what I'm getting from gdb:

Starting program: /home/pi/hdmitester/minimal
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
[New Thread 0xb6a8d450 (LWP 645)]

Thread 1 "minimal" received signal SIGSEGV, Segmentation fault.
KMSDRM_VideoQuit (_this=<optimized out>) at /usr/src/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c:665
665         if (dispdata->conn) {
(gdb) bt
#0  KMSDRM_VideoQuit (_this=<optimized out>) at /usr/src/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c:665
#1  0xb6f40174 in SDL_VideoQuit_REAL () at /usr/src/SDL/src/video/SDL_video.c:2869
#2  0xb6f40c38 in SDL_VideoQuit_REAL () at /usr/src/SDL/src/video/SDL_video.c:2853
#3  SDL_VideoInit_REAL (driver_name=<optimized out>) at /usr/src/SDL/src/video/SDL_video.c:533
#4  0xb6e9d63c in SDL_InitSubSystem_REAL (flags=62001) at /usr/src/SDL/src/SDL.c:206
#5  0x00010aac in main ()

Solution

  • As @genpfault pointed out in comments, SDL ver. 2.0.10 solved Segmentation fault when no HDMI device is present. So if somebody is using hg clone ... or git clone ... make sure you switch to correct version of SDL2 sources before build own version.