bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#8938: make timeout and CTRL-C


From: Pádraig Brady
Subject: bug#8938: make timeout and CTRL-C
Date: Mon, 27 Jun 2011 23:23:07 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.8) Gecko/20100227 Thunderbird/3.0.3

On 27/06/11 21:12, Alan Curry wrote:
> =?UTF-8?Q?P=C3=A1draig?= Brady writes:
>>
>> On 26/06/11 20:20, shay shimony wrote:
>>> all:
>>>         timeout 12 sleep 10
>>>
>>> Note there is a tab before "timeout 12 sleep 10".
>>> Then run at same directory where the file is located "make" and try to press
>>> CTRL-C.
>>>
>>> Notes:
>>> CTRL-Z works.
>>> When executing timeout without make CTRL-C works.
>>> When executing make without timeout CTRL-C works.
>>
>> Drats,
>>
>> That because SIGINT is sent by the terminal to the foreground group.
>> The issue is that `make` and `timeout` use much the same method
>> to control their jobs. I.E. they create their own process group
>> so they can terminate all sub-processes.
> 
> Are you sure? I see no evidence of that. When I run make with the above
> makefile, the processes look like this:
> 
>  PPID   PID  PGID   SID TTY TPGID  STAT  UID   TIME COMMAND
>     1  1451  1451  1451   6 16407  S    1000   0:06 -zsh
>  1451 16407 16407  1451   6 16407  S    1000   0:00 make
> 16407 16408 16408  1451   6 16407  S    1000   0:00 timeout 60 sleep 30
> 16408 16409 16408  1451   6 16407  S    1000   0:00 sleep 30
> 
> The first PGID is the login shell. The second PGID is make, which was put
> into its own process group by the shell because the shell has job control
> enabled. The last PGID is timeout, which put itself into a process group.
> make never noticed any of them.
> 
> In the source for GNU make 3.82 there are no calls to setpgrp or setpgid
> (unless obfuscated from grep). There is the following comment:
> 
>   /* A termination signal won't be sent to the entire
>      process group, but it means we want to kill the children.  */
> 
> That's above the handling of SIGTERM, which iterates over child processes and
> passes along the SIGTERM to them.
> 
> After that is the handling of SIGINT, which doesn't kill child processes
> (unless they're "remote", which is... news to me that make does remote
> things) but just waits for them.
> 
> What seems to be happening is that make *doesn't* create a process group,
> therefore assumes that when it gets a SIGINT, its children have already
> gotten it too, and it just waits for them to die. A child that puts itself
> into a new process group screws this up (as would kill -2 `pidof make`).

Thanks for the analysis Alan.
Yes you're right I think.
In any case the important point is that timeout sets itself as group leader,
and is not the foreground group.

> 
> I think the answer is that timeout should put itself into the foreground.
> That way it would get the SIGINT. make wouldn't get it, but wouldn't need to.
> timeout would exit quickly after SIGINT and make would proceed or abort
> according to the exit code.

I've a version locally here actually that calls tcsetpgrp() but I discounted
that as it's not timeout's place to call that I think.
timeout sets itself as group leader so that it can kill everything it starts,
but it shouldn't need to grab the foreground group as the shell (or make)
may be starting it in the background etc.

So really `make` should not assume children stay in the same group,
and propagate signals down (like it does for TERM).
It might be appropriate for `make` to call tcsetpgrp() before exec..()
but given remote & parallel jobs etc. signal propagation might be best.

I've fixed up `timeout` itself not assume children stay in
the same group, and pass signals on, in the attached patch.

cheers,
Pádraig.

Attachment: timeout-timeout.diff
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]