Paste: nvidia gtk bug

Author: erg (blei)
Mode: factor
Date: Tue, 7 Feb 2012 22:08:21
Plain Text |
#include <stdio.h>
#include <unistd.h>

#include <pthread.h>

#include <gtk/gtk.h>
/*
#include <gtk/gtkgl.h>
*/

/*
 * 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;
}

New Annotation

Summary:
Author:
Mode:
Body: