depfile with multiple outputs triggers a crash

370 views
Skip to first unread message

kw

unread,
Dec 2, 2014, 10:06:50 PM12/2/14
to ninja...@googlegroups.com
I have the following build.ninja file which contains a single build target with multiple outputs along with a generated depfile to indicate implicit dependencies:

rule cgt
   depfile
= c.d
   command
= touch a; touch b; $
      echo
"./a: \\" > c.d; $
      echo
"   /usr/bin/ls" >> c.d; $
      echo
"" >> c.d; $
      echo
"./b: \\" >> c.d; $
      echo
"   /usr/bin/ls" >> c.d; $


build a b
: cgt

If I run `ninja' once in the directory with this file, everything works as expected.  But when I run `ninja' again, it crashes with the following message (I got the message to show by doing a debug build of `ninja'):

/usr/include/c++/4.8.3/debug/safe_iterator.h:264:error: attempt to 
    dereference a singular iterator.
Objects involved in the operation:
iterator "this" @ 0x0x7fffffffd870 {
type = N11__gnu_debug14_Safe_iteratorIN9__gnu_cxx17__normal_iteratorIPP4NodeNSt9__cxx19986vectorIS4_SaIS4_EEEEENSt7__debug6vectorIS4_S8_EEEE (mutable iterator);
  state = singular;
  references sequence with type `NSt7__debug6vectorIP4NodeSaIS2_EEE' @ 0x0x7fffffffd870
}
Program received signal SIGABRT, Aborted.
0x0000003df4435877 in raise () from /lib64/libc.so.6

The highlighted code in src/graph.cc is where it crashes:

84        (*i)->set_dirty(!(*i)->exists());
85      }
86    }
87
88    // If an input is not ready, neither are our outputs.
89    if (Edge* in_edge = (*i)->in_edge()) {
90      if (!in_edge->outputs_ready_)
91        edge->outputs_ready_ = false;
92    }

Here's the backtrace:

#0  0x0000003df4435877 in raise () from /lib64/libc.so.6
#1  0x0000003df4436f68 in abort () from /lib64/libc.so.6
#2  0x0000003e03cb3945 in __gnu_debug::_Error_formatter::_M_error() const ()
   from /lib64/libstdc++.so.6
#3  0x000000000040a49a in __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<Node**, std::__cxx1998::vector<Node*, std::allocator<Node*> > >, std::__debug::vector<Node*, std::allocator<Node*> > >::operator* (this=0x7fffffffd870)
    at /usr/include/c++/4.8.3/debug/safe_iterator.h:262
#4  0x000000000043b137 in DependencyScan::RecomputeDirty (this=0x7fffffffdae0, 
    edge=0x697630, err=0x7fffffffdb10) at src/graph.cc:89
#5  0x0000000000418993 in Builder::AddTarget (this=0x7fffffffda20, 
    node=0x697730, err=0x7fffffffdb10) at src/build.cc:581
#6  0x00000000004074a3 in (anonymous namespace)::NinjaMain::RunBuild (
    this=0x7fffffffdbb0, argc=0, argv=0x7fffffffe010) at src/ninja.cc:898
#7  0x0000000000407f84 in (anonymous namespace)::real_main (argc=0, 
    argv=0x7fffffffe010) at src/ninja.cc:1102
#8  0x0000000000408044 in main (argc=1, argv=0x7fffffffe008)
    at src/ninja.cc:1129

Any idea as to what the problem could be?

Thanks.

Nico Weber

unread,
Dec 3, 2014, 12:15:38 AM12/3/14
to kw, ninja-build
Hi,

thanks for the great bug report!

The depfile parser doesn't expect the shape of your depfile. If an edge has multiple outputs, it expects the depfile to look like this:

  a b: \
     /usr/bin/ls

With this depfile, ninja will then tell you `ninja: error: c.d: depfile has multiple output paths` – depfiles only work with single outputs at the moment. What happens for your depfile is that ninja treats the thing before the first colon ("a") as depfile output, and the rest (/usr/bin/ls, then b (it strips the trailing ':'), then /usr/bin/ls again) as inputs.

So the manifest tells ninja that a and b are built by cgt, but then the depfile tells ninja that a depends on b, which confuses it. It of course shouldn't crash, I filed https://github.com/martine/ninja/issues/875 for that.

As a workaround, you can have your depfile mention only a (and if a and b have different deps, let a depend on the union of the deps of a and b) – since a and b are built at the same time, this should work.

Nico

--
You received this message because you are subscribed to the Google Groups "ninja-build" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ninja-build...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

kw

unread,
Dec 6, 2014, 11:46:51 PM12/6/14
to ninja...@googlegroups.com, wewe...@gmail.com
Thank you very much for the fast reply and the clear explanation!  Your suggestion worked as well. :)
Reply all
Reply to author
Forward
0 new messages