[Top][All Lists]

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

Re: Make does not clean up the target when stderr is piped. Why?

From: Paul Smith
Subject: Re: Make does not clean up the target when stderr is piped. Why?
Date: Fri, 04 Jun 2021 08:57:04 -0400
User-agent: Evolution 3.36.4-0ubuntu1

On Fri, 2021-06-04 at 12:31 +0900, Masahiro Yamada wrote:
> GNU Make cleans up partially updated targets if the user interrupts
> before the build rules complete.
> If GNU Make does not do this, they will not be updated in the next
> run of 'make' because their timestamps are new while the contents are
> incomplete.
> This issue was asked in the Linux kernel ML [1], but I can reproduce
> it in simple test code.  Please see the following case.

It's pretty easy to see what's happening if you use strace.

The thing to remember is that when you use ^C you're sending the signal
to the entire process group.  That means that not only does make get a
SIGINT, but also your "cat" program gets a SIGINT, and dies.

When the SIGINT signal handler is called in GNU make, it tries to clean
up IN THE SIGNAL HANDLER.  This is a long-standing problem, since the
very first version of GNU make as far as I know: it does all kinds of
things in its signal handler which are not really valid in a signal
handler context.

I have a partial solution to fix it, but it's actually extremely
difficult due to the really crappy signal handling model that POSIX
provides and my current solution still suffers from race conditions
that need to be resolved before it can be used.  I haven't had time to
get back to this.

Anyway: one of the things make will do in its signal handler is try to
write error messages to stderr.  If you are piping the output of stderr
to a program, and that program has died, then writing to it will
generate a SIGPIPE.

Because the write is inside the SIGINT signal handler, make is no
longer catching signals like SIGPIPE, so when it receives that SIGPIPE
it will simply exit immediately.

A workaround for your situation, until this whole signal handler thing
can be resolved, is to ignore SIGINT in the program receiving the piped
data so it doesn't die when you hit ^C.

This will work for example:

  $ make 2>&1 | (trap "" 2; cat)
  echo hello > test.txt
  sleep 10
  ^Cmake: *** Deleting file 'test.txt'
  make: *** [/tmp/ test.txt] Interrupt

reply via email to

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