Subject: Re: bug#76943: 30.1; comint-interrupt-subjob does not interrupt process in inferior-python

From: kobarity <[email-masked]>
Date: Thu, 20 Mar 2025 20:43:26 +0900

Eli Zaretskii wrote:
> 
> > Date: Fri, 14 Mar 2025 01:13:29 +0900
> > From: kobarity <[email-masked]>
> > Cc: Garid Zorigoo <[email-masked]>,
> > 	[email-masked]
> > 
> > Eli Zaretskii wrote:
> > > 
> > > > From: Garid Zorigoo <[email-masked]>
> > > > Date: Thu, 13 Mar 2025 11:04:23 +0900
> > > > 
> > > > 
> > > > I found a work around, not sure how & why.
> > > > Changing the value of comint-ptyp seems to make comint-interrupt-subjob work:
> > > > 
> > > >  (setq comint-ptyp nil)
> > > > 
> > > > Hope this helps.
> > > > 
> > > > I believe that inferior-python should be able to interrupt subjobs
> > > > by default (i.e. without the user changing the above variable value).
> > > 
> > > kobarity, any comments or suggestions?
> > 
> > This turned out to be an effect of the setting to make the tty RAW,
> > which Mattias and I did as part of #68559.
> > 
> > (defconst python-shell-setup-code
> >   "\
> > try:
> >     import tty
> > except ImportError:
> >     pass
> > else:
> >     tty.setraw(0)"
> >   "Code used to setup the inferior Python processes.")
> > 
> > This is to disable echo back on MacOS, so there is a workaround to
> > limit this setting to MacOS only.  That would not solve the
> > `comint-interrupt-subjob' problem on MacOS, though.
> > 
> > `comint-ptyp' is passed as the CURRENT-GROUP argument of
> > `interrupt-process' function.  It is finally processed by the
> > process_send_signal function in process.c.  If CURRENT-GROUP is
> > non-nil, it first try to send the control character instead of sending
> > the signal.  However, I believe the control character is ignored
> > because tty is set to RAW by the above code.
> > 
> > I feel it would be better for process_send_signal to check if the tty
> > is RAW, but I am not sure if that is appropriate.
> 
> Paul, WDYT about this?
> 
> > Since process_send_signal checks whether control characters such as
> > VINTR are valid, we can also avoid this problem by disabling VINTR as
> > follows.
> > 
> > (defconst python-shell-setup-code
> >   "\
> > try:
> >     import tty
> >     import termios
> > except ImportError:
> >     pass
> > else:
> >     tty.setraw(0)
> >     attr = termios.tcgetattr(0)
> >     attr[-1][termios.VINTR] = b'\x00'
> >     termios.tcsetattr(0, termios.TCSANOW, attr)"
> >   "Code used to setup the inferior Python processes.")
> > 
> > In summary, there are at least four possible options.
> > 
> > 1. Set `comint-ptyp' to nil.
> > 2. Improve process_send_signal to check if tty is RAW.
> > 3. Disable VINTR in addition to making the tty RAW.
> > 4. Do not set tty to RAW except on MacOS.
> > 
> > If we choose 4, I believe MacOS requires one of 1-3.
> 
> Thanks.
> 
> Let's see what Paul thinks about this, and take it from there.

I have been thinking about it some more too.

> > 1. Set `comint-ptyp' to nil.

This method does not seem to be a solution.  `comint-ptyp' determines
which process group to signal.  For example, when `comint-ptyp' is t,
the foreground process is interrupted instead of Python as follows.

>>> import pty
>>> pty.spawn("/bin/bash")
$ sleep 10
sleep 10
  C-c C-c^C
$

However, when `comint-ptyp' is nil, the Python process is interrupted.

>>> import pty
>>> pty.spawn("/bin/bash")
$ sleep 10
sleep 10
  C-c C-cTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.12/pty.py", line 205, in spawn
    _copy(master_fd, master_read, stdin_read)
  File "/usr/lib/python3.12/pty.py", line 133, in _copy
    _copy(master_fd, master_read=master_read, stdin_read=stdin_read)
  File "/usr/lib/python3.12/pty.py", line 155, in _copy
    rfds, wfds, _xfds = select(rfds, wfds, [])
                        ^^^^^^^^^^^^^^^^^^^^^^
KeyboardInterrupt

So I think the interrupt should work whether `comint-ptyp' is t or
nil.

> > 2. Improve process_send_signal to check if tty is RAW.

More precisely, it would be better to check ISIG of c_lflag.  However,
it may be difficult to change the behavior for compatibility with
previous behavior.

> > 3. Disable VINTR in addition to making the tty RAW.

Another option is to disable echo back only instead of making the tty
raw.  As I mentioned in my earlier mail, `python-shell-setup-code' is
for disabling echo back in MacOS.  Echo back must be disabled for
completion to work, but it is not necessary to make the tty raw.  The
attached patch is to disable echo back only.  Python on Windows is not
affected by this patch because there is no termios module.

Mattias, could you try this patch on MacOS and confirm that completion
works and that ERTs pass?