bugmake - Bugs: bug #15757, circular variable_set_list causes...

 
 

bug #15757: circular variable_set_list causes hang on SunOS

Submitter:  Ab Wilson <abwilson>
Submitted:  Wed 15 Feb 2006 12:24:12 PM UTC
   
 
Severity:  5 - Blocker Item Group:  Bug
Status:  Fixed Privacy:  Public
Assigned to:  psmith Open/Closed:  Closed
Component Version:  3.80 Operating System:  POSIX-Based
Fixed Release:  3.81 Triage Status:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Fri 17 Feb 2006 01:30:48 PM UTC, comment #21: 

OK, I've committed the fix.  I don't know for sure when 3.81 will be available, but it will be soon.

Paul D. Smith <psmith>
Group administrator
Fri 17 Feb 2006 10:46:39 AM UTC, comment #20: 

The fix works. Thanks. Any idea when 3.81 will be officially released?

Ab Wilson <abwilson>
Thu 16 Feb 2006 10:36:20 PM UTC, comment #19: 

OK.  Please try replacing version.c:merge_variable_set_lists() with the one I've attached to this bug report.  See if that solves your problem.  It fixes my test case but the regression tests all still pass.

Paul D. Smith <psmith>
Group administrator
Thu 16 Feb 2006 09:46:16 PM UTC, comment #18: 

Hi.  I can now reproduce this problem, even on Linux, using the following setup:

mkdir t1 t2
touch t1/rules.mk
cd t2
cat > Makefile <<EOF
VPATH = ../t1
include rules.mk
.PHONY: all
all: foo.x
foo.x : rules.mk ; @echo cp $< $@
rules.mk : MYVAR = foo
.INTERMEDIATE: foo.x rules.mk
EOF

Now, still from inside t2, run:
make -I ../t1

and it will loop forever.  The settings for .INTERMEDIATE, target-specific variables, etc. are very particular, to force make into a specific codepath.  I'll look at this more later tonight.

Paul D. Smith <psmith>
Group administrator
Thu 16 Feb 2006 08:34:05 PM UTC, comment #17: 

Oh yeah... using the info you gave and just walking through the logic of merge_variable_set_lists(), you can easily see where the problem happens: global_setlist->next pointer is getting set to point into the "to" setlist.  Ouch.  The logic in this function is completely wrong, at least in this case.  I'll need to understand exactly what it's doing and where else it might be invoked from.

Paul D. Smith <psmith>
Group administrator
Thu 16 Feb 2006 07:23:46 PM UTC, comment #16: 

FYI, the rehash_file() is normally called when a target is found via VPATH.  If the target is found via VPATH, and it is not going to be recreated, then the target name is changed to be the VPATH pathname and the file is re-hashed.  When that happens, if there's already a target with the new name, info on the two targets needs to be combined and that's what this code is doing.

Given the name of the file, I'm guessing that you have an "include rules.mk" and invoke make -I/view/normanw_9.1/vobs/CONNECT_ROOT/bin, or similar, and then you also have in your makefiles "VPATH /view/normanw_9.1/vobs/CONNECT_ROOT/bin" or similar, and then you ALSO have rules.mk as a prerequisite.

To be sure about the first one, can you provide *from_file in the rehash_file() function?

Paul D. Smith <psmith>
Group administrator
Thu 16 Feb 2006 05:49:34 PM UTC, comment #15: 

Good stuff.  Having both of those lists eventually point to global_setlist is, I'm pretty sure, quite correct... all local setlists should eventually point to the global list (this allows global variables to be accessed after all!)  I'll have to look again at the merge_variable_set_lists() code and see what's what.

I sure would like to be able to come up with a test case to reproduce this...

Paul D. Smith <psmith>
Group administrator
Thu 16 Feb 2006 05:44:26 PM UTC, comment #14: 

So this is what's goig on:

merge_variable_set_lists is being called with two non-disjoint lists with the second list longer than the first. The last part of the function where the tail of list1 is appended to list0 results in a circular list.

In this particular instance (*setlist0)->next points to global_setlist, setlist1->next->next->next also points to global_setlist. This is the situation before merge_variable_set_lists is called:


(dbx) where
  [1] _kill(0x0, 0x6, 0xffbfe0f8, 0x0, 0x0, 0x0), at 0xff31ffb0
  [2] abort(0x4b, 0xffbfe188, 0x4b, 0x7efefeff, 0x81010100, 0xff00), at 0xff2b6ce0
  [3] __assert(0x73c7c, 0x73c9c, 0x2f7, 0x0, 0x6b007261, 0x6b007261), at 0xff2b6f80
=>[4] merge_variable_set_lists(setlist0 = 0xf2ea8, setlist1 = 0x3cfbf98), line 759 in "variable.c"
  [5] rehash_file(from_file = 0xb71e98, to_hname = 0x3d0c728 "/view/normanw_9.1/vobs/CONNECT_ROOT/bin/rules.mk"), line 294 in "file.c"
  [6] f_mtime(file = 0xb71e98, search = 1), line 1245 in "remake.c"
  [7] check_dep(file = 0xb71e98, depth = 3U, this_mtime = 1ULL, must_make_ptr = 0xffbfe668), line 969 in "remake.c"
  [8] check_dep(file = 0xd7ff0, depth = 2U, this_mtime = 1ULL, must_make_ptr = 0xffbfe71c), line 1008 in "remake.c"
  [9] update_file_1(file = 0x970d8, depth = 1U), line 505 in "remake.c"
  [10] update_file(file = 0x970d8, depth = 0), line 307 in "remake.c"
  [11] update_goal_chain(goals = 0x1edc00), line 156 in "remake.c"
  [12] main(argc = 5, argv = 0xffbff594, envp = 0xffbff5ac), line 2203 in "main.c"

(dbx) print &global_setlist
&global_setlist = 0x870e4

(dbx) print **setlist0
**setlist0 = {
    (**setlist0).next = 0x870e4
    (**setlist0).set = 0x2ac8b40
}

(dbx) print *setlist1->next->next
*setlist1->next->next = {
    (*setlist1->next->next).next = 0x870e4
    (*setlist1->next->next).set = 0x2be45c8
}

I'm currently investigating rehash_file to try and find the root cause.

Ab Wilson <abwilson>
Thu 16 Feb 2006 04:39:35 PM UTC, comment #13: 

I can confirm that the fix for inode comparisons does not fix this bug.

Ab Wilson <abwilson>
Thu 16 Feb 2006 04:08:58 PM UTC, comment #12: 

We are getting nearer. The problem is actually occuring in merge_variable_set_list. Here is the stack:

(dbx) where
  [1] merge_variable_set_lists(setlist0 = 0xf1868, setlist1 = 0x715fd8), line 735 in "variable.c"
=>[2] rehash_file(from_file = 0xb70858, to_hname = 0x3d0b0e8 "/view/normanw_9.1/vobs/CONNECT_ROOT/bin/rules.mk"), line 294 in "file.c"
  [3] f_mtime(file = 0xb70858, search = 1), line 1245 in "remake.c"
  [4] check_dep(file = 0xb70858, depth = 3U, this_mtime = 1ULL, must_make_ptr = 0xffbfe668), line 969 in "remake.c"
  [5] check_dep(file = 0xd69b0, depth = 2U, this_mtime = 1ULL, must_make_ptr = 0xffbfe71c), line 1008 in "remake.c"
  [6] update_file_1(file = 0x95a98, depth = 1U), line 505 in "remake.c"
  [7] update_file(file = 0x95a98, depth = 0), line 307 in "remake.c"
  [8] update_goal_chain(goals = 0x1ec5c0), line 156 in "remake.c"
  [9] main(argc = 5, argv = 0xffbff594, envp = 0xffbff5ac), line 2203 in "main.c"

Now I don't know whether something went wrong here, or something had earlier made this file's variable list circular. At this point I can't tell because the damage has already been done.

(dbx) print *from_file
*from_file = {
    (*from_file).name   = 0xe08200 "CONNECT_ROOT/bin/rules.mk"
    (*from_file).hname  = 0x3d0b0e8 "/view/normanw_9.1/vobs/CONNECT_ROOT/bin/rules.mk"
    (*from_file).vpath  = (nil)
    (*from_file).deps   = (nil)
    (*from_file).cmds   = (nil)
    command_flags       = 0
    (*from_file).stem   = (nil)
    (*from_file).also_make = (nil)
    last_mtime          = 0
    mtime_before_update = 0
    (*from_file).prev   = (nil)
    (*from_file).renamed = (nil)
    (*from_file).variables = 0x3cfa958
    (*from_file).pat_variables = (nil)
    (*from_file).parent = 0xd69b0
    (*from_file).double_colon = (nil)
    update_status       = -1
    command_state       = cs_not_started
    precious            = 0
    low_resolution_time = 0
    tried_implicit      = 1U
    updating            = 1U
    updated             = 0
    is_target           = 0
    cmd_target          = 0
    phony               = 0
    intermediate        = 1U
    secondary           = 0
    dontcare            = 0
    ignore_vpath        = 0
    pat_searched        = 1U
    considered          = 0
}
(dbx) print *to_file
*to_file = {
    (*to_file).name     = 0xafb48 "/view/normanw_9.1/vobs/CONNECT_ROOT/bin/rules.mk"
    (*to_file).hname    = 0xafb48 "/view/normanw_9.1/vobs/CONNECT_ROOT/bin/rules.mk"
    (*to_file).vpath    = (nil)
    (*to_file).deps     = (nil)
    (*to_file).cmds     = (nil)
    command_flags       = 0
    (*to_file).stem     = (nil)
    (*to_file).also_make = (nil)
    last_mtime          = 1222858067700350979ULL
    mtime_before_update = 1222858067700350979ULL
    (*to_file).prev     = (nil)
    (*to_file).renamed  = (nil)
    (*to_file).variables = 0x2ac9220
    (*to_file).pat_variables = (nil)
    (*to_file).parent   = (nil)
    (*to_file).double_colon = (nil)
    update_status       = 0
    command_state       = cs_finished
    precious            = 0
    low_resolution_time = 0
    tried_implicit      = 1U
    updating            = 0
    updated             = 1U
    is_target           = 0
    cmd_target          = 0
    phony               = 0
    intermediate        = 0
    secondary           = 0
    dontcare            = 0
    ignore_vpath        = 0
    pat_searched        = 1U
    considered          = 0
}

I think I'm going to apply the 64 bit inode patch and see if that's the cause.




Ab Wilson <abwilson>
Thu 16 Feb 2006 11:42:27 AM UTC, comment #11: 

I currently running in dbx with the command:

stop cond find_cycle(&global_setlist)

using

int
find_cycle(const struct variable_set_list* list)
{
  if(!list)
  {
    return 0;
  }
  const struct variable_set_list* one_step = list;
  const struct variable_set_list* two_step = list->next;

  while(
    one_step && one_step->next &&
    two_step && two_step->next && two_step->next->next)
  {
    if(one_step == two_step)
    {
      return 1;
    }
    one_step = one_step->next;
    two_step = two_step->next->next;
  }
  return 0;
}

This is obviously a bit slow but should tell me exactly where global_setlist is becoming circular. I'll post again when I have some results.


Ab Wilson <abwilson>
Wed 15 Feb 2006 08:26:28 PM UTC, comment #10: 

It's a long shot and Paul's method looks like a more constructive way of progressing but I just thought I'd mention bug #15534.  There, make got confused by an apparent inode number collision, caused by only considering the bottom 32 bits of the 64 bit inode number.  Some versions of Solaris might use 64 inode numbers and, the bigger the build, the more likely you are to see a collision.  The bug's fixed in CVS, so it'd be a relatively easy one to eliminate.

Martin Dorey <mdorey>
Wed 15 Feb 2006 07:17:34 PM UTC, comment #9: 

Hrm.  I rechecked the logic (which is somewhat unusual, by necessity) for the variable set list push/pop and it seems correct to me.  That means that there may be somewhere else in the code that's resetting these variables.  It's very odd that it is so difficult to trigger.  There must be something different about this target--or maybe, the target right before this one?!?!

Here's an idea; you could try to narrow down where the problem occurs by adding an assertion at strategic places.  You can't use assert() because you need a statement not a condition, but you can add code like:
  { struct variable_set_list *_p;
    for (_p = global_setlist->next; _p; _p=_p->next)
      if (_p == &global_setlist)
        abort();
  }

which will kill the program when the loop is detected.  You can then add it to various spots (for example variable.c:push_new_variable_scope() and variable.c:pop_variable_scope()).  This may (or may not) help you get closer to the point where the real error is introduced.  It's possible that turning on debugging might help you trace what's going on and see what targets make is considering around when the loop happens.

Paul D. Smith <psmith>
Group administrator
Wed 15 Feb 2006 05:51:58 PM UTC, comment #8: 

I think you can rule out a heap management problem. I added a memset to xmalloc (so all newly allocated memory is explicitly zeroed) and I get the same behaviour.

Regarding OS differences. Yes there are differences. The structure of the make system is based on defaults overridden by platform specifics - so I have generic rules for C++ defined in make/share/c++.mk, these are overridden by reading a platform specific file make/<platform>/c++.mk if it exists. The same model is used to defined all "facilities" available. Is there anything weird about them? Maybe, I'll think about it, but I don't think there are any target specific variables involved.

NB The reason I'm using 3.81beta on Solaris is that 3.80 dumped core on these makefiles, but I think at a different place.

Ab Wilson <abwilson>
Wed 15 Feb 2006 05:38:44 PM UTC, comment #7: 

Thanks for the info.  I need to look at it a bit.

There are no fixed size anything in GNU make; everything is dynamic.  Your guess is logical, but in fact there is an explanation that fits the facts better that doesn't rely on any resource issue: running "make foo" and "make everything" where everything is a target that eventually depends on foo, is very different in one critical aspect that bears directly on this situation: target-specific variables are inherited through the dependency chain, and this feature is one of the things that is facilitated by that next pointer.  So, the longer your chain is from the "top" the more entries are added to/removed from the chain of variable sets.

Thus, if you run "make foo" your chain may be only one level deep, while if you run "make everything" by the time make starts to build "foo", your chain may be 5 levels deep (say).

I need to check your debug results and compare them with the code and think about this more.  I'm actually more concerned with the fact that you don't see this on Linux, which seems to imply that it's less of an algorithm error and more of a heap management error (as you say, maybe memory is not being initialized on Solaris).  Bizarre.  Unless, there is something non-trivially different about your build on Solaris vs. Linux?  Maybe there is conditional code depending on the host OS?  Or, Solaris has extra target-specific variables defined?  Or...?

Paul D. Smith <psmith>
Group administrator
Wed 15 Feb 2006 05:14:23 PM UTC, comment #6: 

Further to...

The structure of these makefiles is such that make has a global view of everything, but if I type make with no arguments it will build all the targets and their prerequisites for the current directory (including those prerequisites from outside the current directory). If I do this in the directory which was failing I don't see the problem but if I build the target everything which depends on targets for the current directory the problem occurs. This leads me to believe that it is not the particular combination of rules for the directory which is causing the problem, but the shear overal complexity of working with the dependencies for the whole source tree. Are there any fixed sized buffers etc you can think of which may limit the code size make can work with?

Ab Wilson <abwilson>
Wed 15 Feb 2006 04:34:00 PM UTC, comment #5: 

tower% pstack 16636
16636:  /home/normanw/sparc-SunOS-5.8/bin/make --warn-undefined-variables ever
 0004bea4 target_environment (8b5b90, 2, 1, 0, 2f736800, 85698) + 1b4
 00032704 start_job_command (2bb8ed8, 0, ffffffff, fffffff8, 0, 2bb8e09) + 664
 00032af8 start_waiting_job (2bb8ed8, 0, ffffffff, fffffff8, 0, 2bb8f05) + c0
 000334c4 new_job  (8b5b90, 0, a, 1, 2bb8ed8, 96a40) + 80c
 00021810 execute_file_commands (8b5b90, 745f0, 21d90, ff33c000, 4, 9e319) + f0
 00046e7c remake_file (8b5b90, 9, 14, 0, 2f686f73, 0) + f4
 00045914 update_file_1 (8b5b90, 8, 0, 0, 0, 1) + 192c
 00043d10 update_file (8b5b90, 8, 0, 1, 8b5b90, 0) + 118
 00044cf0 update_file_1 (2bba1b8, 0, d2cf8, 2baa640, 0, 1) + d08
 00043d10 update_file (2bba1b8, 7, 1a, 1a, 2bba1b8, 0) + 118
 00046274 check_dep (2bba1b8, 6, 0, 1, ffbfe4a8, ffbfdf30) + cc
 00046878 check_dep (91c8c8, 5, 0, 1, ffbfe548, 0) + 6d0
 00046878 check_dep (71c178, 4, 0, 1, ffbfe5fc, ff0000) + 6d0
 00044958 update_file_1 (71c0f8, 3, 0, ad03e8, 0, 1) + 970
 00043d10 update_file (71c0f8, 3, 26, 26, 71c0f8, 0) + 118
 00046274 check_dep (71c0f8, 2, 0, 1, ffbfe7a8, 6bb2b0) + cc
 00046878 check_dep (11be20, 1, 0, 1, ffbfe85c, ace1b9) + 6d0
 00044958 update_file_1 (94818, 0, a14d28, 21d140, 0, 1) + 970
 00043d10 update_file (94818, 0, ffbfe931, 2, 94818, 0) + 118
 0004361c update_goal_chain (92ab0, 0, d702a0, 0, 0, ace1a0) + 204
 00037b18 main     (4, ffbff6d4, 9aaf0, 95478, 0, 0) + 2b58
 0001f0e8 _start   (0, 0, 0, 0, 0, 0) + 108

(dbx) print *file
*file = {
    (*file).name        = 0xb70ff0 "/bld/tower/normanw_9.1/share/host/gateways/src/.mkdir"
    (*file).hname       = 0xb70ff0 "/bld/tower/normanw_9.1/share/host/gateways/src/.mkdir"
    (*file).vpath       = (nil)
    (*file).deps        = (nil)
    (*file).cmds        = 0x96a40
    command_flags       = 0
    (*file).stem        = 0x2b83e38 "/bld/tower/normanw_9.1/share/host/gateways/src"
    (*file).also_make   = (nil)
    last_mtime          = 1ULL
    mtime_before_update = 0
    (*file).prev        = (nil)
    (*file).renamed     = (nil)
    (*file).variables   = 0x2b83778
    (*file).pat_variables = (nil)
    (*file).parent      = 0x71d450
    (*file).double_colon = (nil)
    update_status       = -1
    command_state       = cs_not_started
    precious            = 0
    low_resolution_time = 0
    tried_implicit      = 1U
    updating            = 0
    updated             = 0
    is_target           = 1U
    cmd_target          = 0
    phony               = 0
    intermediate        = 1U
    secondary           = 0
    dontcare            = 0
    ignore_vpath        = 0
    pat_searched        = 1U
    considered          = 1U
}

(dbx) print *file->variables
*file->variables = {
    (*file->variables).next = 0x2bb9220
    (*file->variables).set = 0x2b83710
}
(dbx) print *file->variables->next
*file->variables->next = {
    (*file->variables->next).next = 0x85698
    (*file->variables->next).set = 0x2bb8aa0
}
(dbx) print *file->variables->next->next
*file->variables->next->next = {
    (*file->variables->next->next).next = 0x1dbed08
    (*file->variables->next->next).set = 0x8aed8
}
(dbx) print *file->variables->next->next->next
*file->variables->next->next->next = {
    (*file->variables->next->next->next).next = 0x85698
    (*file->variables->next->next->next).set = 0xacd9b8
}
(dbx) print global_setlist
global_setlist = {
    global_setlist.next = 0x1dbed08
    global_setlist.set = 0x8aed8
}
(dbx) print &global_setlist
&global_setlist = 0x85698
(dbx) print current_variable_set_list
current_variable_set_list = 0x85698
(dbx) print *current_variable_set_list
*current_variable_set_list = {
    (*current_variable_set_list).next = 0x1dbed08
    (*current_variable_set_list).set = 0x8aed8
}

The target file is a dummy file used to force directory creation. I have a pattern rules something like:

%/.mkdir:
  mkdir -p $(@D) && touch $(@)

I use this technique for creating directories absolutely everywhere.

The actual chain of dependencies looks like:

everything: /bld/tower/normanw_9.1/sparc-SunOS-5.9/dyn_dbg/CONNECT_ROOT/FSSGateway/src/FSSGateway

/bld/tower/normanw_9.1/sparc-SunOS-5.9/dyn_dbg/CONNECT_ROOT/FSSGateway/src/FSSGateway: -lhostgateways

-lhostgateways: /bld/tower/normanw_9.1/sparc-SunOS-5.9/dyn_dbg/lib/libhostgateways.so

/bld/tower/normanw_9.1/sparc-SunOS-5.9/dyn_dbg/host/gateways/src/manifest.o: host/gateways/src/manifest.cpp

host/gateways/src/manifest.cpp: /bld/tower/normanw_9.1/share/host/gateways/src/.mkdir

everything is a phony target to build everything in the tree. The -l target is another phony target which depends on the actual library file. There is a target specific variable defined on the library basically setting up its linker options. The library depends on the dot-o files which are platform specific. There are  pattern specific variables set up to set compilation options at a source directory level. The manifest.cpp target is a generated file listing the versions to be built. It's built by a pattern rule looking something like:

$(shr_root)/%/manifest.cpp: \
  $(shr_root)/%/.mkdir

Where $(shr_root) is the root for shared targets under the build tree (we build for different architectures with different variants, the shr_root contains platfrom independent targets).

However, having said all that I don't think this particular combination of dependencies is special since every source directory has a manifest.cpp file defined in exactly the same way, and make happily get through building about half the source before getting stuck. I could try just building the directory which is causing the problems.

Ab Wilson <abwilson>
Wed 15 Feb 2006 03:37:55 PM UTC, comment #4: 

Yes, it's OK for global_setlist->next to be non-null in some situations.  This is very helpful, but can you repeat the test and provide the same info you did in both examples (that is, backtrace, *file, trace the ->next pointers through to the loop, plus show the value of the global_setlist variable and its address) and also show the value of current_variable_set_list and *current_variable_set_list?

Also, if you could print file->name then check your makefiles for that target and see if there is anything unusual about it (target-specific or pattern-specific variable settings for it, for example).  Also, you might walk back up the recursion and see what target path (foo depends on bar depends on baz ...) got you to this point, and look at those targets for any target-specific variables as well.  It would be REALLY great if we could find a way to reproduce this, even just on Solaris.

Paul D. Smith <psmith>
Group administrator
Wed 15 Feb 2006 03:08:49 PM UTC, comment #3: 

And another thing...

(dbx) print global_setlist
`make`variable.c`global_setlist = {
    `make`variable.c`global_setlist.next = 0x49fd08
    `make`variable.c`global_setlist.set = 0x51b508
}
(dbx) print &global_setlist
&`make`variable.c`global_setlist = 0x85670

This is from a different run BTW.

Should global_setlist.next ever be non-null?

Ab Wilson <abwilson>
Wed 15 Feb 2006 02:54:11 PM UTC, comment #2: 

Ok, this is a pstack of a stuck make process:

tower% pstack -F 13172
13172:  /home/normanw/sparc-SunOS-5.8/bin/make -k variants=dyn_dbg --warn-unde
 0004be50 target_environment (91dd30, 2, 1, 0, 2f736800, 85670) + 178
 00032704 start_job_command (2bba118, 91dd30, 3fd20, 3fdf8, 3fed0, 2bba049) + 664
 00032af8 start_waiting_job (2bba118, 0, ffffffff, fffffff8, 0, 2bba145) + c0
 000334c4 new_job  (91dd30, 0, a, 1, 2bba118, 96be8) + 80c
 00021810 execute_file_commands (91dd30, 745f0, 21d90, ff33c000, 4, 9e4c9) + f0
 00046e64 remake_file (91dd30, 9, 14, 0, 2f686f73, 0) + f4
 000458fc update_file_1 (91dd30, 8, 0, 0, 0, 1) + 192c
 00043cf8 update_file (91dd30, 8, 0, 1, 91dd30, 0) + 118
 00044cd8 update_file_1 (2bbaff8, 0, d0188, 2bba7b8, 0, 1) + d08
 00043cf8 update_file (2bbaff8, 7, 1a, 1a, 2bbaff8, 0) + 118
 0004625c check_dep (2bbaff8, 6, 0, 1, ffbfe360, ffbfdde8) + cc
 00046860 check_dep (701868, 5, 0, 1, ffbfe400, 0) + 6d0
 00046860 check_dep (51e370, 4, 0, 1, ffbfe4b4, ff0000) + 6d0
 00044940 update_file_1 (51e2f0, 3, 0, a8eae0, 0, 1) + 970
 00043cf8 update_file (51e2f0, 3, 26, 26, 51e2f0, 0) + 118
 0004625c check_dep (51e2f0, 2, 0, 1, ffbfe660, 679b98) + cc
 00046860 check_dep (120900, 1, 0, 1, ffbfe714, 0) + 6d0
 00044940 update_file_1 (949c8, 0, a14050, 21c458, 0, 1) + 970
 00043cf8 update_file (949c8, 0, ffbfe7d9, 2, 949c8, 0) + 118
 00043604 update_goal_chain (92b00, 0, cebfe0, 0, 0, a7d718) + 204
 00037b18 main     (5, ffbff58c, 9b6b0, 9b0b0, 0, 0) + 2b58
 0001f0e8 _start   (0, 0, 0, 0, 0, 0) + 108

I can burrow down through file->variables->next->next->next etc...

(dbx) print *file->variables
*file->variables = {
    (*file->variables).next = 0x2bba4a0
    (*file->variables).set = 0x2b84388
}
(dbx) print *file->variables->next
*file->variables->next = {
    (*file->variables->next).next = 0x85670
    (*file->variables->next).set = 0x2bb9ce0
}
(dbx) print *file->variables->next->next
*file->variables->next->next = {
    (*file->variables->next->next).next = 0x1dbf868
    (*file->variables->next->next).set = 0x8aeb0
}
(dbx) print *file->variables->next->next->next
*file->variables->next->next->next = {
    (*file->variables->next->next->next).next = 0x85670
    (*file->variables->next->next->next).set = 0xa7c6b0
}

Is that any use to you?


Ab Wilson <abwilson>
Wed 15 Feb 2006 02:11:51 PM UTC, comment #1: 

This problem does not ring a bell with me, unfortunately.  We're going to need your help to debug it.  Can you provide a backtrace?  Please make sure you build make with debugging enabled so that we get decent symbols etc.  Is the argument to the function (file) set or not?  If it's set, please check that target and tell me if there are any target-specific or pattern-specific variables set for it.  It would be interesting to know whether the incorrect NEXT pointer is in the target-specific list, or the global list.  I suppose it must be in the target-specific list.

You can try building the CVS code, or I'll probably be making another prerelease within the next few days.

Paul D. Smith <psmith>
Group administrator
Wed 15 Feb 2006 12:24:12 PM UTC, original submission:  

I'm using make-3.81beta4 on Solaris SunOS 5.9 compiled with Sun cc 5.5.

I have a large non-recursive make system which builds around 250 directories of source code. I'm seeing make hang after building roughly half the source. Running up the debugger I see that it's actually going round in circles in the function variable.c:target_environment. This is due to the variable list associated with the target file being circular. The outer loop:

for (s = set_list; s != 0; s = s->next)

is non-terminating because at some point s->next is somehow ending up pointing back at a previous member of the list.

I'm using the same make system to build the same source tree on Linux (Red Hat enterprise 2.6.9-22.0) using make 3.80 and everything works fine, so this is clearly a platform issue. I'm speculating that the error is due to differences in the behaviour of malloc on the two platforms - ie on Solaris malloc is giving back a previously used variable_set_list object with an (accidentally) valid next pointer. But, this is idle speculation.

The bug is easily reproducible but only with a large set of makefiles.

Is this a known issue? I having found anything in the achieves relating to it.

Ab Wilson <abwilson>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #1918:  mvnew.c added by psmith (826B - text/x-csrc - New version.c:merge_variable_set_lists() function)

 

Depends on the following items: None found

Items that depend on this one: None found

 

CC list is empty

 

There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

Only logged-in users can vote.

 

Follow 8 latest changes.

Date Changed by Updated Field Previous Value => Replaced by
2006-04-01 psmith Fixed Release4.0 3.81
2006-02-17 psmith StatusNone Fixed
    Open/ClosedOpen Closed
    Component VersionNone 3.80
    Fixed ReleaseNone 4.0
2006-02-16 psmith Attached File- Added mvnew.c, #3408
2006-02-16 psmith Severity3 - Normal 5 - Blocker
    Assigned toNone psmith

Back to the top

Powered by Savane 3.13-4448.
Corresponding source code