无法再 ctrl-c 我的 SDL 应用程序

标签 c linux opengl signals sdl

昨天我可以,今天我不能在终端中使用 ctrl-c 来终止我的 SDL 应用程序。在调用 SDL_Init 之前,一切都按预期进行。之后,ctrl-c 什么都不做。调用 signal(SIGINT, SIG_DFL) 不会改变这一点。除了 Nvidia 驱动程序,我没有更新任何我能想到的东西。我几个月前编译的应用程序也会出现这种情况。

有什么方法可以调试正在发生的事情吗?

[编辑]
即使这在 SDL_Init 之后停止工作(尽管在 gdb 中正常运行):

signal(SIGINT, exit);
raise(SIGINT);

SDL1.2.15 和 SDL2 都发生了同样的情况(虽然过剩是可以的)。我正在运行 Fedora 18 (x64)、gcc 4.7.2、带有 gtx titan 的 nvidia 驱动程序 331.2。

SDL_QUIT 当我点击窗口上的关闭按钮时发生,但从未 ctrl-c (afaik 它从来没有用过 - SIGINT 只会杀死应用程序)。

[EDIT2]
这不是始终可重现的,但很常见。有时预先运行其他程序,例如 echo 可以增加 ctrl-c 工作的机会。如果它不起作用,重复永远不会起作用。

经过进一步测试后,似乎只有当 SDL_INIT_TIMER 传递给 SDL_Init 时,ctrl-c 才会停止工作。 定时器子系统与信号有什么关系?

[EDIT3]
这是我的测试用例...

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <SDL2/SDL.h>

int main()
{
    SDL_Window* window = NULL;
    SDL_GLContext context;

    fprintf(stderr, "Start");
    usleep(3000000);
    fprintf(stderr, ".\n");

    //raise(SIGINT); //always works

    struct sigaction old;
    sigaction(SIGTERM, NULL, &old);

    fprintf(stderr, "Init");
    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE);
    //SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE); //no problems
    fprintf(stderr, ".\n");
    usleep(3000000);

    sigaction(SIGINT, &old, NULL);
    //signal(SIGINT, SIG_DFL);
    //raise(SIGINT); //fails with SDL_INIT_TIMER (commonly, but not always)

    fprintf(stderr, "Window");
    window = SDL_CreateWindow("sdlwin", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    fprintf(stderr, ".\n");
    usleep(3000000);

    fprintf(stderr, "Context");
    context = SDL_GL_CreateContext(window);
    fprintf(stderr, ".\n");
    usleep(3000000);

    fprintf(stderr, "Loop...\n");
    while (1)
    {
        usleep(1000000);
        printf(".\n");
    }
    return 0;
}

在某些情况下,第一个 ctrl-c 就可以了。有时,第一个结束当前的 usleep 并且需要一秒钟才能终止应用程序。其他时候,ctrl-c 永远不起作用。随机性让我假设某处有未初始化的东西。令人恼火的是,我刚刚运行了一次,其中 ctrl-c 90% 的时间都有效,只有几次失败。

最佳答案

在查看了 SDL 源代码后,似乎将 SDL_INIT_EVENTS 传递给 SDL_Init 将导致 SDL 使用其自己的信号处理函数。在 SDL_quit.c 中,我们有:

/* Both SIGINT and SIGTERM are translated into quit interrupts */
(and the code that does that)

你可以简单地用

反转它
#include <signal.h>
...
struct sigaction action;
sigaction(SIGINT, NULL, &action);
SDL_Init(SDL_INIT_EVERYTHING);
sigaction(SIGINT, &action, NULL);
....

SDL 信号处理程序除了将 SDL_QUIT 事件推送到事件队列(并重置信号处理程序)外什么都不做,因此如果您不需要处理退出,只需将其反转即可事件。

默认情况下,ctrl+c 应该将 SDL_QUIT 推送到事件队列中。在我的电脑上,只要创建了一个窗口,它就以这种方式工作。尝试打印所有轮询事件的类型,并查看 ctrl+c 是否发送任何事件。此外,如果您使用的是 SDL 1,请考虑使用 SDL 2

关于无法再 ctrl-c 我的 SDL 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20049025/

相关文章:

c - C代码的用户界面

开奖分配C语言程序出现.exe错误

linux - 内核如何通知用户空间程序中断发生

c++ - 使用立即模式绘制纹理的 OpenGL 替代方案?

linux - 如何启用 vtk "direct"硬件渲染,X11/Ubuntu 11.04 x86-64?

c - 在 C 中链接库

Android:带 USB-C 适配器的耳机按钮

node.js - 为什么我无法安装特定版本的 npm 以及如何安装?

c++ - OpenGL 缺少 Glut32

c - 指向链表开头的指针