Subject: bug#407: gpm server stop making emacs abort()

From: Kevin Ryde <[email-masked]>
Date: Fri, 31 Oct 2008 09:11:07 +1100

Stefan Monnier <[email-masked]> writes:
>
> Huh!  Indeed!  The condition "gpm < 0" is encountered all the time,

Yes, EWOULDBLOCK.  gpm==0 is eof from the server.

gpm==-1 is a protocol error as well as EWOULDBLOCK, but it might be ok
to quietly ignore that.  It probably only happens if libgpm.so and the
running daemon are incompatible versions.

I get some joy from the change below.  I think the add/delete descriptor
calls might be right, but I'm not terrifically confident.

One thing I notice not done is to turn off the gpm-mouse-mode minor mode
variable when stopping like this.  Maybe that's good enough.  It won't
stop normally, so as long as emacs doesn't abort that could be enough.
(You can M-x gpm-mouse-mode twice to toggle it back on.)

*** keyboard.c	31 Oct 2008 08:25:09 +1100	1.977
--- keyboard.c	31 Oct 2008 08:25:19 +1100	
***************
*** 7102,7118 ****
    {
        Gpm_Event event;
        struct input_event hold_quit;
!       int gpm;
  
        EVENT_INIT (hold_quit);
        hold_quit.kind = NO_EVENT;
  
        while (gpm = Gpm_GetEvent (&event), gpm == 1) {
  	  nread += handle_one_term_event (tty, &event, &hold_quit);
        }
!       if (gpm < 0)
! 	/* Presumably the GPM daemon has closed the connection.  */
! 	close_gpm ();
        if (hold_quit.kind != NO_EVENT)
  	  kbd_buffer_store_event (&hold_quit);
        if (nread)
--- 7102,7123 ----
    {
        Gpm_Event event;
        struct input_event hold_quit;
!       int gpm, fd;
  
        EVENT_INIT (hold_quit);
        hold_quit.kind = NO_EVENT;
  
+       /* gpm==1 if event received.
+          gpm==0 if the GPM daemon has closed the connection, in which case
+                 Gpm_GetEvent closes gpm_fd and clears it to -1, so save that
+                 for close_gpm() to remove from the select masks.
+          gpm==-1 if a protocol error or EWOULDBLOCK; the latter is normal. */
+       fd = gpm_fd;
        while (gpm = Gpm_GetEvent (&event), gpm == 1) {
  	  nread += handle_one_term_event (tty, &event, &hold_quit);
        }
!       if (gpm == 0)
! 	close_gpm (fd);
        if (hold_quit.kind != NO_EVENT)
  	  kbd_buffer_store_event (&hold_quit);
        if (nread)
*** term.c	31 Oct 2008 08:23:59 +1100	1.229
--- term.c	31 Oct 2008 08:24:05 +1100	
***************
*** 3129,3138 ****
  }
  
  void
! close_gpm ()
  {
!   if (gpm_fd >= 0)
!     delete_gpm_wait_descriptor (gpm_fd);
    while (Gpm_Close()); /* close all the stack */
    gpm_tty = NULL;
  }
--- 3129,3139 ----
  }
  
  void
! close_gpm (fd)
!      int fd;
  {
!   if (fd >= 0)
!     delete_gpm_wait_descriptor (fd);
    while (Gpm_Close()); /* close all the stack */
    gpm_tty = NULL;
  }
***************
*** 3150,3156 ****
    if (!tty || gpm_tty != tty)
      return Qnil;       /* Not activated on this terminal, nothing to do.  */
  
!   close_gpm ();
    return Qnil;
  }
  #endif /* HAVE_GPM */
--- 3151,3157 ----
    if (!tty || gpm_tty != tty)
      return Qnil;       /* Not activated on this terminal, nothing to do.  */
  
!   close_gpm (gpm_fd);
    return Qnil;
  }
  #endif /* HAVE_GPM */
*** termhooks.h	13 Sep 2008 07:34:28 +1000	1.98
--- termhooks.h	30 Oct 2008 18:54:52 +1100	
***************
*** 644,650 ****
  extern struct terminal *initial_terminal;
  
  #ifdef HAVE_GPM
! extern void close_gpm (void);
  #endif
  
  /* arch-tag: 33a00ecc-52b5-4186-a410-8801ac9f087d
--- 644,650 ----
  extern struct terminal *initial_terminal;
  
  #ifdef HAVE_GPM
! extern void close_gpm P_ ((int));
  #endif
  
  /* arch-tag: 33a00ecc-52b5-4186-a410-8801ac9f087d

-- 
The sigfile one-line movie review series:
"Cold Fever" -- easily the best Japanese-Icelandic road movie ever made.