0
votes

I'm writing a muti-thread program using xlib, pthread and cairo. This program create a thread in order to draw ten points after a click event.

The problem is:

After the program drew three points, it got crashed and xlib complaint

X Error of failed request:  BadRequest (invalid request code or no such operation)
  Major opcode of failed request:  0 ()
  Serial number of failed request:  67
  Current serial number in output stream:  97

However, it can work properly when I'm using strace like "strace ./a.out".

Here's my code-clips:

void *draw_point(void *arg) { //paint random-postion point
    int i = 0;
    int seed;
    double x ,y;
    srand(seed);
    cairo_set_source_rgba (cairo, 1, 0.2, 0.2, 0.6);
    for(i = 0; i< 10; i++) {
        x = rand() % 200;
        y = rand() % 200;
        if(candraw) {
            cairo_arc (cairo, x, y, 10.0, 0, 2*M_PI);
            cairo_fill (cairo);
        }
        hasdraw = true;
        sleep(1);
    }
    return NULL;
}

bool win_main(void)
{
    int clickx = 0, clicky = 0;
    unsigned long valuemask;
    XEvent event;

    valuemask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionMask;

    XSelectInput(display, win, valuemask);

    pthread_t thread;

    while (1) {
        while (XPending(display) == 0) {
            candraw = true;
            if(hasdraw)
            XFlush(display);
            candraw = false;
        }
        XNextEvent(display, &event);
        candraw = false;
        switch (event.type) {
        case MotionNotify:
            //...
            break;
        case ButtonPress:
            clickx = event.xbutton.x;
            clicky = event.xbutton.y;
            if(clicky < 50)
                pthread_create(&thread, NULL, draw_point, NULL);
            break;
        case ButtonRelease:
            //...
            break;
        default:
            break;
        }
    }
    return 0;
}

Does anyone has an idea about this weird problem? Thanks a lot!

1

1 Answers

1
votes

The problem is caused by using multi-threading with the 2 threads trying to access the display at the same.

strace will change the timing, so the threads are accessing the display at different times.

Xlib does have functions to prevent conflict. Lookup XInitThreads, which enables thread support and XLockDisplay and XUnlockDisplay, which you will need to call from each thread before and after accessing the display.