I'm experimenting Xlib and thread local storage on linux 2.6, and i'm trying to open one connection to the X server by thread, but it seems not to work. I try to create a window, to set inputmask to ButtonPressMask, then to wait events in each threads. And it segfault after receiving an event. In fact even in the same thread, i can't open multi connection to the same X server, i receive this error, just after the opening of a first window: -=- feanor@tolfalas:~/wd$ ./open-multi-display X Error of failed request: BadWindow (invalid Window parameter) Major opcode of failed request: 2 (X_ChangeWindowAttributes) Resource id in failed request: 0x3800001 Serial number of failed request: 8 Current serial number in output stream: 9 -=- I attach my two test programs for you to see. @+
/* Copyright 2003 Benjamin Dauvergne <feanor@xxxxxxxxxxxxxxx> */ /* Compile: -g -L/usr/X11R6/lib -lX11 */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <X11/Xlib.h> Display *display1, *display2; Window wid1, wid2; int screen1, screen2; int main(int argc, char **argv) { display1 = XOpenDisplay(":0"); display2 = XOpenDisplay(":0"); screen1 = DefaultScreen(display1); screen2 = DefaultScreen(display2); XInitThreads(); wid1 = XCreateSimpleWindow(display1, RootWindow(display1, screen1), 0, 0, 100, 100, 0, BlackPixel(display1, screen1), WhitePixel(display1, screen1)); wid1 = XCreateSimpleWindow(display2, RootWindow(display2, screen2), 0, 0, 100, 100, 0, BlackPixel(display2, screen2), WhitePixel(display2, screen2)); XSelectInput(display1, wid1, ButtonPressMask); XSelectInput(display2, wid2, ButtonPressMask); XMapWindow(display1, wid1); XMapWindow(display2, wid2); while(1) { XEvent event; if (XCheckMaskEvent(display1, ButtonPressMask, &event)) { printf("Click1\n"); continue; } if (XCheckMaskEvent(display2, ButtonPressMask, &event)) { printf("Click2\n"); continue; } sleep(1); } return 0; }
/* Copyright 2003 Benjamin Dauvergne <feanor@xxxxxxxxxxxxxxx> */ /* Compile: -g -L/usr/X11R6/lib/ -lX11 -lpthread */ #include <cstdio> extern "C" { #include <X11/Xlib.h> #include <pthread.h> } using namespace std; static __thread bool _display_class_init = false; class display { public: static __thread Display *_display; static __thread pthread_t _self; void _init() { _display = XOpenDisplay(NULL); if (! _display) throw; _self = pthread_self(); } public: display() { XInitThreads(); if (!_display_class_init) _init(); _display_class_init = true; } ~display() { XCloseDisplay(_display); } // If we are in another thread than where display object was created // create a new connection to X operator Display*() { if (_self != pthread_self()) _init(); return _display; } void mainLoop() { XEvent report; while(1) { printf("Thread %d in event loop %p\n", _self, _display); XNextEvent(display(), &report); } } }; display context; class window { public: Window wid; window(int x, int y, int w, int h, bool t) { wid = XCreateSimpleWindow(context, RootWindow((Display*)context, DefaultScreen((Display*)context)), x, y, w, h, 0, ( t ? BlackPixel((Display*)context, DefaultScreen((Display*)context)) : WhitePixel((Display*)context, DefaultScreen((Display*)context))), ( ! t ? BlackPixel((Display*)context, DefaultScreen((Display*)context)) : WhitePixel((Display*)context, DefaultScreen((Display*)context)))); } void map() { XMapWindow(context, wid); } void setInputMask(long event_mask) { XSelectInput(context, wid, event_mask); } }; void *main2(void *d) { window w(50,50,300,300,true); w.map(); w.setInputMask(ButtonPressMask); printf("window id %d %d %p\n", w.wid, display::_self, display::_display); context.mainLoop(); } __thread Display *display::_display; __thread pthread_t display::_self; int main(int argc, char **argv) { pthread_t one_thread; pthread_create(&one_thread, 0, main2, NULL); window w(10,10,100,100,false); w.setInputMask(ButtonPressMask); printf("window id %d %d %p\n", w.wid, display::_self, display::_display); w.map(); context.mainLoop(); }