#include #include #include #include /* #include */ /* * NOTE: at first I tried to create a GL context to reproduce the hang (see the * out-commented code.) But apparently it's not required to actually use GL at * all, linking to GL makes the bug appear. * * Build this with: * gcc foo.c -Wall `pkg-config --libs --cflags gtk+-2.0` -lGL * (If you are on Ubuntu, you might have to add -Wl,--no-as-needed to * reproduce) * * The commented code requires (but is not needed to reproduce): * gcc foo.c -Wall `pkg-config --libs --cflags gtk+-2.0 gtkglext-1.0` * * Description: * An empty window opens. When you close the window, the executable doesn't * stop, but appears to hit an endless loop. If you connect to the executable * with GDB, you can see that the endless loop happens in the NVidia driver. * My guess as to the cause of the loop is that the NVidia driver intercepts * the read() call and waits for it to finish (in a spinning loop) in an * function that was registered using at_exit() or something similar. * * System information: * Arch Linux, Kernel 3.2.2 * Nvidia 290.10 * GTK 2.24.9 * * Thank you for looking into this :) */ void *read_stuff(void *data) { sigset_t mask; sigfillset(&mask); sigdelset(&mask, SIGUSR2); sigdelset(&mask, SIGTTIN); sigdelset(&mask, SIGTERM); sigdelset(&mask, SIGQUIT); pthread_sigmask(SIG_SETMASK, &mask, NULL); int unused; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &unused); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &unused); while (1) { char buf[1000]; // read from stdin read(0, buf, 1000); } return NULL; } void start_read_thread() { pthread_t thread_id; pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&thread_id, &attr, read_stuff, NULL); } int main(int argc, char **argv) { start_read_thread(); gtk_init(&argc, &argv); GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* int config_attribs[] = {GDK_GL_USE_GL, GDK_GL_RGBA, GDK_GL_DOUBLEBUFFER, GDK_GL_ATTRIB_LIST_NONE}; GdkGLConfig *config = gdk_gl_config_new(config_attribs); gtk_widget_set_gl_capability(window, config, NULL, TRUE, GDK_GL_RGBA_TYPE); */ g_signal_connect(window, "delete-event", gtk_main_quit, NULL); gtk_widget_show_all(window); gtk_main(); return 0; }