Question

I have a Xlib-based program with an event loop that uses XNextEvent to receive and process relevant events.

I would like to be able to gracefully close this program from another process (actually from a shell script). I need to do some cleanup when closing, so I considered to setup a signal handler (for example for SIGUSR1) and when this signal is received, do the appropriate cleanup.

My question is, how can I interrupt the (blocking) XNextEvent call from the signal handler?

Any other suggestions?

Was it helpful?

Solution

I found a way to do this based on this SO question and this one.

Basically you can use the ConnectionNumber() macro to get the fd that XNextEvent() is reading from. This lets me call select() myself to wait for data on the Xlib fd and some other fd. Now it is select() that is blocking, and not XNextEvent(). I can easily unblock select() from my signal handler by writing to the second fd.

Pseudo-code for the event loop:

/* Get X11 fd */
x11_fd = ConnectionNumber(display);

while(1) {
    /* Create a File Description Set containing x11_fd and other_fd */
    FD_ZERO(&in_fds);
    FD_SET(x11_fd, &in_fds);
    FD_SET(other_fd, &in_fds);

    /* Wait for X Event or exit signal */
    ret = select(nfds, &in_fds, ...);
    if (FD_ISSET(other_fd, &in_fds) {
        /* Do any cleanup and exit */
    } else {
        while (XEventsQueued(display, QueuedAlready) > 0) {
            /* Process X events */
        }
    }
}

OTHER TIPS

Assuming you have the process id, you can use the kill function:

int kill(pid_t pid, int sig);

You can send any signal but SIGKILL (SIGKILL cannot be handled)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top