Another pipe-related problem?

Henry S. Thompson ht@inf.ed.ac.uk
Tue Nov 9 10:55:26 GMT 2021


Ken Brown via Cygwin writes:

> On 11/8/2021 8:12 AM, Henry S. Thompson via Cygwin wrote:
>> Running on Windows-10 21H1
>>
>> With Cygwin 3.3.0 and 3.3.1 I get a hang every time I try to launch XEmacs:
>>
>> ..
>> #6  0x000000018013ffcc in read (fd=3, ptr=0xffff0bc0, len=<optimized out>)
>>      at /usr/src/debug/cygwin-3.3.1-1/winsup/cygwin/dtable.h:64
>> #7  0x000000018018e88b in _sigfe () at sigfe.s:35
>> #8  0x000000010066a11d in retry_read_1 (fildes=3, buf=0xffff0bc0, nbyte=128,
>>      allow_quit=0) at sysdep.c:2425
>> #9  0x000000010066a171 in retry_read (fildes=3, buf=0xffff0bc0, nbyte=128)
>>      at sysdep.c:2437
>> #10 0x0000000100494d86 in drain_signal_event_pipe () at event-unixoid.c:159
>> #11 0x000000010056d1dc in mswindows_need_event (badly_p=1) at event-msw.c:1432
>>
>> This is an old executable, has worked since 2015 (!), but recompiling
>> didn't help.  Reverting to 3.2 lets it run again.
>
> This backtrace doesn't match the source of Cygwin's XEmacs package
> (which exists on 32-bit Cygwin only), so I assume you built this
> yourself, using a different version of XEmacs.  Cygwin's XEmacs
> doesn't hang for me.

Thanks for looking in to this!

And you're right, it's a local build.  I was responsible for producing
the 64-bit XEmacs back in 2015, but could never get a Visual Studio
build to work at that time, so it was never released.

> Please provide build instructions for the version you compiled.

As you may know, the XEmacs situation is complicated.  The old source
repo (bitbucket.org/xemacs) no longer exists.  There's a fork that's
still being maintained, but it's not widely publicised.  That's the
one I'm working with -- are you aware of this.

> Your backtrace shows that fhandler_pipe::raw_read is blocked waiting
> for a mutex, but I can't tell why without seeing the XEmacs source.
> My guess, just from looking at the function names, is that XEmacs is
> mixing POSIX reads with Win32 reads, messing up the mutex handling.

If you have access to the public sources vintage mid-2015 or later,
the following might work:

  ./configure  '--with-pdump=yes' '--with-modules=no' '--with-mule=yes' '--with-ncurses=yes' '--with-msw=yes' '--with-xpm' '--with-tls=no' '--without-x'
  make
  src/xemacs --vanilla

Otherwise let me know and I'll point you at the current repo.

Here are the immediate contexts from the sources for the xemacs
sources in the above backtrace, might be enough to check your
hypothesis:

sysdep.c:

  retry_read_1 (int fildes, void *buf, size_t nbyte, int allow_quit)
  {
    ssize_t rtnval;

    while ((rtnval = read (fildes, buf, nbyte)) == -1
           && (errno == EINTR))
      {
        if (allow_quit)
          QUIT;
      }
    return rtnval;
  }

  ssize_t
  retry_read (int fildes, void *buf, size_t nbyte)
  {
    return retry_read_1 (fildes, buf, nbyte, 0);
  }

event-unixoid.c:

  drain_signal_event_pipe (void)
  {
    Rawbyte chars[128];
    /* The input end of the pipe has been set to non-blocking. */
    while (retry_read (signal_event_pipe[0], chars, sizeof (chars)) > 0)
      ;
  }

event-msw.c:

  /*
   * This drains the event queue and fills up two internal queues until
   * an event of a type specified by USER_P is retrieved.
   *
   *
   * Used by emacs_mswindows_event_pending_p and emacs_mswindows_next_event
   */
  static void
  mswindows_need_event (int badly_p)
  {
    while (NILP (dispatch_event_queue)
           && NILP (mswindows_s_dispatch_event_queue))
      {
  #ifdef CYGWIN
        int i;
        int active;
        SELECT_TYPE temp_mask = input_wait_mask;
        EMACS_TIME sometime;
        EMACS_SELECT_TIME select_time_to_block, *pointer_to_this;

        if (badly_p)
          pointer_to_this = 0;
        else
          {
            EMACS_SET_SECS_USECS (sometime, 0, 0);
            EMACS_TIME_TO_SELECT_TIME (sometime, select_time_to_block);
            pointer_to_this = &select_time_to_block;
            if (in_modal_loop)
              /* In modal loop with badly_p false, don't care about
                 Windows events. */
              FD_CLR (windows_fd, &temp_mask);
          }

        mswindows_is_blocking = 1;
        active = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this);
        mswindows_is_blocking = 0;

        if (active == 0)
          {
            assert (!badly_p);
            return;               /* timeout */
          }
        else if (active > 0)
          {
            if (FD_ISSET (windows_fd, &temp_mask))
              mswindows_drain_windows_queue (badly_p);
            else
              {
  #ifdef HAVE_TTY
                /* Look for a TTY event */
                for (i = 0; i < MAXDESC; i++)
                  {
                    /* To avoid race conditions (among other things, an infinite
                       loop when called from Fdiscard_input()), we must return
                       user events ahead of process events. */
                    if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask))
                      {
                        struct console *c =
                          find_tty_or_stream_console_from_fd (i);
                        Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
                        Lisp_Event *event = XEVENT (emacs_event);

                        assert (c);
                        if (read_event_from_tty_or_stream_desc (event, c))
                          {
                            mswindows_enqueue_dispatch_event (emacs_event);
                            return;
                          }
                      }
                  }
  #endif
                /* Look for a process event */
                for (i = 0; i < MAXDESC; i++)
                  {
                    if (FD_ISSET (i, &temp_mask))
                      {
                        if (FD_ISSET (i, &process_only_mask))
                          {
                            Lisp_Process *p =
                              get_process_from_usid (FD_TO_USID (i));

                            mswindows_enqueue_process_event (p);
                          }
                        else
                          {
                            /* We might get here when a fake event came
                               through a signal. Return a dummy event, so
                               that a cycle of the command loop will
                               occur. */
                            drain_signal_event_pipe ();
                            mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE);
                          }
                      }
                  }
              }
          }
        else if (active == -1)
          {
            if (errno != EINTR)
              {
                /* something bad happened */
                assert (0);
              }
          }
        else
          {
            assert (0);
          }
  #else /* not CYGWIN */
  ...

Thanks again,

ht
-- 
       Henry S. Thompson, School of Informatics, University of Edinburgh
      10 Crichton Street, Edinburgh EH8 9AB, SCOTLAND -- (44) 131 650-4440
                Fax: (44) 131 650-4587, e-mail: ht@inf.ed.ac.uk
                       URL: http://www.ltg.ed.ac.uk/~ht/
 [mail from me _always_ has a .sig like this -- mail without it is forged spam]

The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.



More information about the Cygwin mailing list