sensing X connection failure/timeout

Yann Droneaud ydroneaud at mandriva.com
Wed Sep 30 01:56:32 PDT 2009


Le mardi 29 septembre 2009 à 13:08 -0500, Xavier Toth a écrit :
> I'm displaying clients on a remote X server and if I power the X
> server box or pull the network cable some of the clients never
> terminate. Some clients (fbpanel and gnome-screensaver in particular)
> terminate and write "Fatal IO error 110 (Connection timeout) on X
> server  <ip address>" to stderr, openbox the window manager we are
> using does not ever realize that the server is gone. Looking at the
> openbox main loop code:
> 

[...]

> I see that if there are no X event it does a select on an fd set
> initialized as follows:
> 
[...]

> with a wait of NULL (infinite) and it never returns.
> 
> What is the proper way to determine that a remote server connection
> has failed or timed out?
> 

Once upon a time, I wrote this. As other good story, this one start by:

while(1)
{
    /** wait for a read event
     * there's no need to check for exception condition:
     * there's none, see man 7 socket
     *
     * it would be better to use ppoll(), but it's not widely available
     *
     */

    sigemptyset(&signal_mask);

    n = pselect(FD_SETSIZE, &fdset, NULL, NULL,
                NULL, &signal_mask);

    if (n < 0) {

      /* interrupted, OK, just retry */
      if (errno == EINTR || errno == EAGAIN || errno == EINPROGRESS)
        continue;

      /* real error, retry */
      /* XXX: count number of error */
      DPRINTF( "select() failed: %s\n", strerror(errno));

      continue;
    }

    if (n == 0) {
      /* timeout ! */
      continue;
    }
    if (FD_ISSET(XConnectionNumber(display), &fdset)) {

      /* read some events (do not flush output buffer) */
      if (XEventsQueued(display, QueuedAfterReading)) {

        do {

          /* extract an event from the input queue */
          XNextEvent(display, &e);

          printf("event %d\n",
                 e.type);

          /* XXX process the event */


        } while(XEventsQueued(display, QueuedAlready));

        /*
         * send the output data,
         * since XNextEvent will never do it for us,
         * because the input queue will never be empty
         * when it is called.
         *
         */
        XFlush(display);
      } else {
        /* read condition, but no event, check for EOF */

        struct pollfd pfd;

        pfd.fd = XConnectionNumber(display);
        pfd.events = POLLIN;
        pfd.revents = 0;

        n = poll(&pfd, 1, 0);
        if (n <= 0) {
          DPRINTF("poll() failed: %s\n", strerror(errno));
        }

        if (n == 1) {

          DPRINTF("poll() returned 0x%04x\n", (unsigned int)
pfd.revents);

          if (pfd.revents & POLLNVAL) {
            DPRINTF("poll() failed: invalid file descripor\n");
          }

          if (pfd.revents & POLLERR) {
            DPRINTF("poll() returned POLLERR\n");
          }

          if (pfd.revents & POLLHUP) {
            DPRINTF("poll() returned POLLHUP\n");

          }
         if (pfd.revents & POLLIN) {
            DPRINTF("poll() returned POLLIN\n");
          }


          if (pfd.revents & POLLHUP) {

            int pending = 0;

            /* if no read condition or no data in the socket: EOF */
            if (!(pfd.revents & POLLIN) ||
                (ioctl(XConnectionNumber(display), FIONREAD, &pending) !
= 0 ||
                 pending == 0)) {

              /* connection closed */
#if 0
              XSync(display, True); /* just go crazy: process errors,
                                       discard queues */
              XCloseDisplay(display);
#endif
             /*
               * can't do more than that:
               * calling XSync() or XCloseDisplay() generate SIGPIPE
               * since they wrote on the connexion regardless of the
status
               *
               * but, it's at least better than the default error
function
               *
               */
              fprintf(stderr, "Lost connexion to X server\n");
              close(XConnectionNumber(display));
              exit(0);
            }
          }
        }
      }
    }


But beware of signals hidden in the woods.

Regards.

-- 
Yann Droneaud






More information about the xorg mailing list