昨天我可以,今天我不能在终端中使用 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/