You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Wayland环境下SDL2程序拖拽文件时崩溃并提示‘Wayland display connection closed by server’的问题咨询

Wayland环境下SDL2程序拖拽文件时崩溃并提示‘Wayland display connection closed by server’的问题咨询

问题描述

我在Fedora 38(Wayland会话)上使用SDL2 2.32.56版本开发窗口程序,实现了基础事件循环并处理文件拖拽相关事件。当将文件拖拽到窗口上时,程序会正常打印BeginDropfileComplete的日志,但随后立即崩溃,报错信息为Wayland display connection closed by server (fatal)

我的核心逻辑是在SDL_DROPFILE事件触发后,打印日志并调用SDL_free(event.drop.file)释放拖拽得到的文件路径字符串,之后程序就会触发崩溃。

重现代码

#include <stdio.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <stdlib.h> // 补充缺失的头文件,EXIT_SUCCESS/EXIT_FAILURE依赖它

#define WINDOW_TITLE "TEST"
#define SCREEN_WIDTH 1000
#define SCREEN_HEIGHT 1000

struct Game
{
    SDL_Window *window;
    SDL_Renderer *renderer;
};

void game_cleanup(struct Game *game, int exit_status);
bool sdl_initialze(struct Game *game);

int main()
{
    struct Game game =
    {
        .window = NULL,
        .renderer = NULL,
    };
    
    if(sdl_initialze(&game))
    {
        game_cleanup(&game,EXIT_FAILURE);
    }
 
    while (true) 
    {
        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
            switch (event.type)
            {
            case SDL_QUIT:
                game_cleanup(&game, EXIT_SUCCESS);
                break;
            
            case SDL_DROPFILE:
                SDL_Log("Dropfile");
                SDL_free(event.drop.file);
                break;

            case SDL_DROPBEGIN:
                SDL_Log("Begin");
                break;

            case SDL_DROPCOMPLETE:
                SDL_Log("Complete");
                break;    

            case SDL_KEYDOWN:
                switch (event.key.keysym.scancode)
                {
                case SDL_SCANCODE_ESCAPE:
                    game_cleanup(&game, EXIT_SUCCESS);
                    break;
                
                default:
                    break;
                }
                break;

            default:
                break;
            }
        }
        SDL_RenderClear(game.renderer);
        
        SDL_RenderPresent(game.renderer);

        SDL_Delay(16);    
    }

    SDL_Log("Hello World\n");
    game_cleanup(&game, EXIT_SUCCESS);
    return 0;
} 

void game_cleanup(struct Game *game, int exit_status)
{
    SDL_DestroyRenderer(game->renderer);
    SDL_DestroyWindow(game->window);
    SDL_Quit();
    exit(exit_status);
}

bool sdl_initialze(struct Game *game)
{
    if(SDL_Init(SDL_INIT_EVERYTHING))
    {
        fprintf(stderr, "SDLINIT failed %s", SDL_GetError());
        return true;    
    }

    game->window = SDL_CreateWindow(WINDOW_TITLE,SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
    if(!game->window)
    {
        fprintf(stderr, "WINDOW Creating failed %s", SDL_GetError());
        return true;   
    }

    game->renderer = SDL_CreateRenderer(game->window, -1, 0);
    if(!game->renderer)
    {
        fprintf(stderr, "Renderer Creating failed %s", SDL_GetError());
        return true;   
    }

    return false;
}

问题排查与解决方案

可能原因分析

这个崩溃大概率是SDL 2.32.56版本的Wayland后端存在的已知bug。Wayland下SDL的文件拖拽依赖xdg-dnd协议实现,旧版本SDL在处理拖拽事件的资源释放时,可能会触发Wayland compositor的连接异常断开。

另外,你的代码原本缺失#include <stdlib.h>头文件(EXIT_SUCCESS/EXIT_FAILURE的定义来源),虽然这不是崩溃的直接原因,但会引发未定义行为,建议先补充。

可行解决方案尝试

  1. 优先升级SDL2版本
    SDL在2.34.0及以上版本中修复了多个Wayland后端的拖拽相关bug。你可以通过Fedora包管理器更新到最新稳定版:

    sudo dnf update SDL2 SDL2-devel
    

    或者从SDL官方源码编译安装最新版本。

  2. 临时切换X11会话规避
    切换到X11会话运行程序,验证是否为Wayland后端特有问题。如果X11下运行正常,即可确认是旧版本SDL Wayland后端的bug导致崩溃。

  3. 强制使用X11后端运行
    作为临时规避方案,设置环境变量强制SDL使用X11后端:

    SDL_VIDEO_DRIVER=x11 ./your_program
    
  4. 禁用Wayland拖拽功能
    通过环境变量关闭Wayland下的拖拽支持:

    SDL_VIDEO_WAYLAND_DISABLE_DND=1 ./your_program
    

验证建议

如果升级SDL2到最新版本后,Wayland下拖拽文件不再崩溃,即可确认是旧版本SDL的Wayland后端bug导致的问题。若问题仍存在,可前往SDL官方Issue Tracker提交问题,附带你的测试环境和代码细节以寻求进一步支持。

火山引擎 最新活动