help-make
[Top][All Lists]
Advanced

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

Re: Questions about signal handling in GNU Make


From: Kaz Kylheku (gmake)
Subject: Re: Questions about signal handling in GNU Make
Date: Fri, 23 Jul 2021 14:19:55 -0700
User-agent: Roundcube Webmail/0.9.2

On 2021-07-23 09:48, Masahiro Yamada wrote:
Hi.


GNU Make deletes partially updated target files
when it is interrupted.

Yes, unless the targets are mentioned in the
.PRECIOUS: special target.

The description of PRECIOUS leads to the documentation
section "Interrupting or Killing 'make'" which
describes the requirements and rationale.

I am interested in this behavior.
I did not look into the source code,
but did some experiments to understand how GNU
Make behaves.

Ctrl-C is a normal way to terminate GNU Make.

Well, not really depending on what we mean by
"normal". A build usually runs to successful
or failed completion.

Using Ctrl-C is usual in interactive development,
so the behavior seen here could be an annoyance
in the right circumstances.

I don't see this being an issue in CI pipelines.

CI systems that can interrupt builds will typically
not re-run builds incrementally the same sandbox;
if an interrupted build is retriggered, it will be
done from scratch in a fresh sandbox.

$ cat Makefile
test.txt:
        ./create-file.sh $@

$ cat create-file.sh
#!/bin/bash
echo hello > $1
sleep 30
echo bye >> $1

This looks like it will potentially fool make, according
to the documented requirements, which say this:

  If 'make' gets a fatal signal while a shell is executing,
  it may delete the target file that the recipe was supposed
  to update. This is done if the target file's last-modification
  time has changed since 'make' first checked it.

This is clear; the event for triggering the deletion is
GNU Make receiving a fatal signal, not GNU make having
waited for all the children to exit.

In other words, what's going on in the box is what is written
on the side of the box; this is a requirements problem.

A good requirement would be that GNU Make should wait for
all the jobs to terminate, and then check for non-PRECIOUS
target files whose time stamp has changed and delete them.

That said ...

Your script tickles the race condition because it contains
multiple opens of the file. Each "echo hello > $1" statement
separately opens the $1 file, creating it if necessary.

There will be no problem with any single-open tool. E.g.
if a C compiler writes a .o file by opening the file just once,
and then performing one or more writes, then this issue
cannot happen.

Even if the compiler continues writing to the file after
GNU make has processed the SIGINT, it is writing to an orphaned
file which no longer has a directory entry, and which will
disappear when that compiler exits.

For that reason, I don't think this is a severe bug.

Firstly, build tools should not be opening output files
more than once, ideally.

Secondly, build tools which open a file more than once
should not specify O_CREAT for the second and subsequent
times. The second and subsequent opens should expect
the file to exist, and fail otherwise.

I mean, think about it. Suppose you have a compiler
which repeatedly opens an object file to deposit more
functions into it as it is progressing through the
source file.  Should it simply not care that
the file disappeared halfway through and just newly
create the file, adding the new content to it, even
though earlier content is gone?

The only way $@ should be open more than once is if multiple
steps in the GNU Makefile itself make multiple references to
it:

   pizza: $(INGREDIENTS)
      mix-dough $@ ;; opens
      let-rise $@  ;; opens
      roll-flat $@ ;; opens
      ...

Here we don't have a problem because Make's execution of
the recipe stops when it gets the SIGINT; it won't race
against itself.

Nevertheless, roll-flat should complain if the pizza
does not exist! It should expect dough that has been
mixed and allowed to rise.

Cheers ...



reply via email to

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