Sending signals to a subprocess

Ken Brown kbrown@cornell.edu
Wed Oct 20 03:20:00 GMT 2010


On 10/19/2010 10:15 AM, Christopher Faylor wrote:
> On Tue, Oct 19, 2010 at 09:32:34AM -0400, Ken Brown wrote:
>> On 10/18/2010 4:18 PM, Christopher Faylor wrote:
>>> On Mon, Oct 18, 2010 at 03:40:21PM -0400, Ken Brown wrote:
>>>> On 10/18/2010 2:34 PM, Christopher Faylor wrote:
>>>>> On Sat, Oct 16, 2010 at 02:06:56PM -0400, Ken Brown wrote:
>>>>>> On 10/16/2010 1:17 PM, Ken Brown wrote:
>>>>>>> I could use some help fixing a longstanding bug in the Cygwin build of
>>>>>>> emacs, in which emacs is unable to send signals to subprocesses.  A
>>>>>>> symptom from the user's point of view is that one cannot interrupt a
>>>>>>> process in shell mode by typing C-c C-c.  I've found a workaround that
>>>>>>> handles that case (SIGINT), as well as SIGQUIT and SIGTSTP.  But as long
>>>>>>> as I'm fixing this, I'd like to do it right and figure out how to handle
>>>>>>> all signals.
>>>>>>>
>>>>>>> This boils down to finding the right process group ID to pass to 'kill'.
>>>>>>> On systems that have TIOCGPGRP, emacs uses the following code (in
>>>>>>> src/process.c) to get this ID:
>>>>>>>
>>>>>>> /* Return the foreground process group for the tty/pty that
>>>>>>>         the process P uses.  */
>>>>>>> static int
>>>>>>> emacs_get_tty_pgrp (p)
>>>>>>>           struct Lisp_Process *p;
>>>>>>> {
>>>>>>>        int gid = -1;
>>>>>>>
>>>>>>> #ifdef TIOCGPGRP
>>>>>>>        if (ioctl (p->infd, TIOCGPGRP,&gid) == -1&&     ! NILP (p->tty_name))
>>>>>>>          {
>>>>>>>            int fd;
>>>>>>>            /* Some OS:es (Solaris 8/9) does not allow TIOCGPGRP from the
>>>>>>> 	 master side.  Try the slave side.  */
>>>>>>>            fd = emacs_open (SDATA (p->tty_name), O_RDONLY, 0);
>>>>>>>
>>>>>>>            if (fd != -1)
>>>>>>> 	{
>>>>>>> 	  ioctl (fd, TIOCGPGRP,&gid);
>>>>>>> 	  emacs_close (fd);
>>>>>>> 	}
>>>>>>>          }
>>>>>>> #endif /* defined (TIOCGPGRP ) */
>>>>>>>
>>>>>>>        return gid;
>>>>>>> }
>>>>>>>
>>>>>>> What's the right way to do this in Cygwin?
>>>>>>
>>>>>> I guess it's clear from the context, but I should have said that the
>>>>>> problem only arises when emacs has to communicate with the subprocess
>>>>>> through a tty that is not the controlling tty of emacs.  So tcgetpgrp()
>>>>>> doesn't work.
>>>>>
>>>>> I am a little confused as to the difference between tcgetpgrp and
>>>>> TIOCGPGRP given this man page description from "man 4 tty_ioctl" on
>>>>> linux:
>>>>>
>>>>>           TIOCGPGRP pid_t *argp
>>>>>                  When successful, equivalent to *argp = tcgetpgrp(fd).
>>>>>                  Get the process group ID of the foreground process group on this terminal.
>>>>>
>>>>>           TIOCSPGRP const pid_t *argp
>>>>>                  Equivalent to tcsetpgrp(fd, *argp).
>>>>>                  Set the foreground process group ID of this terminal.
>>>>>
>>>>> Do you have a simple test case which demonstrates the difference between
>>>>> the calls?  It seems odd that TIOCGPGRP would allow more access to a tty
>>>>> than tcgetpgrp.
>>>>
>>>> The difference is that, according to POSIX, tcgetpgrp is required to
>>>> fail unless fd references the controlling terminal of the calling
>>>> process.  Ironically, Cygwin's tcgetpgrp used to succeed in this
>>>> situation until Corinna fixed it a year ago:
>>>>
>>>>     http://www.cygwin.com/ml/cygwin-patches/2009-q4/msg00045.html
>>>
>>> Yes, I got that but TIOCGPGRP seems to have that same limitation on
>>> Linux.  That's why I quoted the above man page.  A simple test case
>>> (tm) seems to bear out the fact that the two are the same.
>>
>> I just tried an experiment, and now I'm thoroughly confused.  I inserted
>> "#undef TIOCGPGRP" into process.c in the emacs source and rebuilt it on
>> Linux.  [Technical note if anyone wants to try to reproduce this: I also
>> inserted "#undef SIGNALS_VIA_CHARACTERS", since SIGNALS_VIA_CHARACTERS
>> provides an alternate method of sending signals to processes; this is in
>> fact my workaround on Cygwin.]  Then trying to kill a process running in
>> an emacs shell with C-c C-c fails the same way it fails in Cygwin.  So
>> somehow TIOCGPGRP is doing the right thing under Linux in the emacs code
>> above, in spite of its limitations.  I don't understand why.  When I get
>> a chance (not today), I'll try running emacs under gdb to see if I can
>> figure out what's going on.
>>
>> I guess this should mean that if you implement TIOCGPGRP in Cygwin and
>> make it emulate Linux, it should work for emacs in Cygwin too.  I can
>> also try to see if tcgetpgrp works instead of TIOCGPGRP.  I'm
>> embarrassed to say that I didn't actually try this before, because my
>> understanding of the documentation was that it wouldn't work.  You can
>> see I don't think like a programmer.
>
> As I mentioned, my test case shows that when run on Linux, TIOCPGRP and
> tcgetpgrp are the same.  So, given that, if I implemented TIOCPGRP it
> wouldn't solve your problem.

You're right.  I'm convinced now that TIOCGPGRP and tcgetpgrp are the 
same on Linux, so implementing TIOCGPGRP would not help me.  To 
double-check, I rewrote the emacs code to use tcgetpgrp instead of 
TIOCGPGRP, and it worked on Linux just as well as before.  But the same 
code fails on Cygwin.  I don't understand why it works on Linux, because 
it appears to me to be using tcgetpgrp in the situation where it's 
supposed to fail

I would like to create a STC that would let me investigate this further, 
but I don't know enough programming to do it. It ought to be completely 
trivial.  Here's what happens:

Emacs creates a subprocess that runs an interactive bash shell.  Emacs 
wants to get the PGID of the foreground process group associated to the 
tty of this shell, and it does this on Linux via TIOCGPGRP (or equally 
well tcgetpgrp).  I think it uses the file descriptor of the master of 
the pty for this purpose.  If you (or some other programmer reading 
this) could give me the code for setting all this up, I could play with 
it and try to figure out why I'm seeing a difference between Linux and 
Cygwin here.  I just don't know how to create a subprocess, give it a 
terminal, etc.

Ken

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple



More information about the Cygwin mailing list