From: Tim Olsen <tim@brooklynpenguin.com>
To: git@vger.kernel.org
Cc: git@vger.kernel.org, Miklos Vajna <vmiklos@frugalware.org>,
Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: Re: git-merge segfault in 1.6.6 and master
Date: Wed, 20 Jan 2010 16:57:19 -0500 [thread overview]
Message-ID: <4B577C3F.7040608@brooklynpenguin.com> (raw)
In-Reply-To: <7vocko3802.fsf@alter.siamese.dyndns.org>
Junio C Hamano wrote:
> Thanks.
Thanks for taking the time to look into this!
>
> Since you can build and run git yourself, can I ask you to run another
> experiment with this one-liner patch applied?
It appears that a segfault still happens with your patch applied, but
this time it is caught:
tolsen@neurofunk:~/git/site-build-dav-sync-05 [git:build-dav-sync-05]$
git merge origin/deployed
error: merge-recursive died of signal 11
Merge with strategy recursive failed.
tolsen@neurofunk:~/git/site-build-dav-sync-05 [git:build-dav-sync-05]$
> "common = NULL" means merged_common_ancestors->tree is NULL in the caller.
> Somebody is passing a bogus commit in "ca" (aka common ancestors) list
> when calling merge_recursive(), or forgetting to parse them before calling
> it. In your debugger could you find out where it comes from and what it
> has before this call into merge_trees() is made? Specifically, what the
> "ca" list at 0x7b3c00 contains, and how "merged_common_ancestors" at
> 0x121e360 looks like. in this trace we see below:
Here is the replay of the flow of execution from the first time we enter
merge_recursive(). The repository has been modified slightly so the
pointers are different this time but the segfault is still happening
(I'll stop modifying the repository now ;-) .
Upon entering merge_recursive() for the first time, ca is a two-item
list and both items have non-null trees:
Breakpoint 1, merge_recursive (o=0x7fffffffd560, h1=0x793350,
h2=0x7932c0, ca=0x7b4a40, result=0x7fffffffd5d8) at merge-recursive.c:1286
(gdb) p *ca
$1 = {item = 0x793db8, next = 0x7b4a20}
(gdb) p *(ca->next)
$2 = {item = 0x793aa0, next = 0x0}
(gdb) p ca->item->tree
$3 = (struct tree *) 0x77be10
(gdb) p ca->next->item->tree
$4 = (struct tree *) 0x77b488
(gdb)
Then on line 1303, the head of ca is popped off into
merged_common_ancestors:
Breakpoint 2, merge_recursive (o=0x7fffffffd560, h1=0x793350,
h2=0x7932c0, ca=0x7b4a20, result=0x7fffffffd5d8) at merge-recursive.c:1304
(gdb) list
1299 for (iter = ca; iter; iter = iter->next)
1300 output_commit_title(o, iter->item);
1301 }
1302
1303 merged_common_ancestors = pop_commit(&ca);
1304 if (merged_common_ancestors == NULL) {
1305 /* if there is no common ancestor, make an empty tree */
1306 struct tree *tree = xcalloc(1, sizeof(struct tree));
1307
1308 tree->object.parsed = 1;
(gdb) p merged_common_ancestors
$5 = (struct commit *) 0x793db8
(gdb) p ca
$8 = (struct commit_list *) 0x7b4a20
merge_recursive() is then called recursively at line 1329 with a pointer
to merged_common_ancestors passed as the "result" argument:
Breakpoint 3, merge_recursive (o=0x7fffffffd560, h1=0x793350,
h2=0x7932c0, ca=0x7b4a20, result=0x7fffffffd5d8) at merge-recursive.c:1329
(gdb) list
1324 discard_cache();
1325 saved_b1 = o->branch1;
1326 saved_b2 = o->branch2;
1327 o->branch1 = "Temporary merge branch 1";
1328 o->branch2 = "Temporary merge branch 2";
1329 merge_recursive(o, merged_common_ancestors, iter->item,
1330 NULL, &merged_common_ancestors);
1331 o->branch1 = saved_b1;
1332 o->branch2 = saved_b2;
1333 o->call_depth--;
(gdb)
In the second call to merged_common_ancestors(), result's pointee is
replaced by a commit with a null tree at line 1347:
Breakpoint 4, merge_recursive (o=0x7fffffffd560, h1=0x793db8,
h2=0x793aa0, ca=0x0, result=0x7fffffffd500) at merge-recursive.c:1347
(gdb) n
(gdb) p (*result)->tree
$10 = (struct tree *) 0x0
(gdb) list
1343 clean = merge_trees(o, h1->tree, h2->tree,
merged_common_ancestors->tree,
1344 &mrtree);
1345
1346 if (o->call_depth) {
1347 *result = make_virtual_commit(mrtree, "merged tree");
1348 commit_list_insert(h1, &(*result)->parents);
1349 commit_list_insert(h2, &(*result)->parents->next);
1350 }
1351 flush_output(o);
1352 return clean;
(gdb)
make_virtual_commit() is just setting its tree to mrtree:
Breakpoint 5, make_virtual_commit (tree=0x0, comment=0x5016fc "merged
tree") at merge-recursive.c:44
(gdb) list
39 * A virtual commit has (const char *)commit->util set to the name.
40 */
41
42 static struct commit *make_virtual_commit(struct tree *tree, const
char *comment)
43 {
44 struct commit *commit = xcalloc(1, sizeof(struct commit));
45 commit->tree = tree;
46 commit->util = (void*)comment;
47 /* avoid warnings */
48 commit->object.parsed = 1;
(gdb)
49 return commit;
50 }
At the beginning of merge_recursive(), the local mrtree appears to be
set to some globally defined mrtree which is not null:
Breakpoint 1, merge_recursive (o=0x7fffffffd560, h1=0x793db8,
h2=0x793aa0, ca=0x0, result=0x7fffffffd500) at merge-recursive.c:1286
(gdb) p mrtree
$13 = (struct tree *) 0x7ffff732d0ac
(gdb) list
1281 struct commit_list *iter;
1282 struct commit *merged_common_ancestors;
1283 struct tree *mrtree = mrtree;
1284 int clean;
1285
1286 if (show(o, 4)) {
1287 output(o, 4, "Merging:");
1288 output_commit_title(o, h1);
1289 output_commit_title(o, h2);
1290 }
(gdb)
Which leads me to believe the problem is in the call to merge_trees() at
line 1343:
Breakpoint 6, merge_recursive (o=0x7fffffffd560, h1=0x793db8,
h2=0x793aa0, ca=0x0, result=0x7fffffffd500) at merge-recursive.c:1343
(gdb) list
1338
1339 discard_cache();
1340 if (!o->call_depth)
1341 read_cache();
1342
1343 clean = merge_trees(o, h1->tree, h2->tree,
merged_common_ancestors->tree,
1344 &mrtree);
1345
1346 if (o->call_depth) {
1347 *result = make_virtual_commit(mrtree, "merged tree");
(gdb)
In merge_trees(), mrtree is the argument **result. It is at line 1255
that write_tree_from_memory nulls out the pointee of result:
Breakpoint 7, merge_trees (o=0x7fffffffd560, head=0x77be10,
merge=0x77b488, common=0x77c0b8, result=0x7fffffffd478) at
merge-recursive.c:1255
(gdb) p *result
$16 = (struct tree *) 0x7ffff732d0ac
(gdb) n
(gdb) p *result
$17 = (struct tree *) 0x0
(gdb) list
1252 clean = 1;
1253
1254 if (o->call_depth)
1255 *result = write_tree_from_memory(o);
1256
1257 return clean;
1258 }
1259
1260 static struct commit_list *reverse_commit_list(struct commit_list
*list)
1261 {
(gdb)
Then in write_tree_from_memory() we find the offending return NULL at
line 210:
Breakpoint 8, write_tree_from_memory (o=0x7fffffffd560) at
merge-recursive.c:210
(gdb) list
205 struct cache_entry *ce = active_cache[i];
206 if (ce_stage(ce))
207 output(o, 0, "%d %.*s", ce_stage(ce),
208 (int)ce_namelen(ce), ce->name);
209 }
210 return NULL;
211 }
212
213 if (!active_cache_tree)
214 active_cache_tree = cache_tree();
(gdb)
Let me know if you need any more information.
Thanks,
Tim
next prev parent reply other threads:[~2010-01-20 21:58 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-01-20 16:17 git-merge segfault in 1.6.6 and master Tim Olsen
2010-01-20 19:13 ` Junio C Hamano
2010-01-20 21:57 ` Tim Olsen [this message]
2010-01-20 22:21 ` Junio C Hamano
2010-01-21 16:37 ` Tim Olsen
2010-01-21 18:12 ` Junio C Hamano
2010-01-22 0:21 ` Junio C Hamano
2010-01-22 0:38 ` Junio C Hamano
2010-01-21 14:00 ` Miklos Vajna
2010-01-21 21:56 ` Tim Olsen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4B577C3F.7040608@brooklynpenguin.com \
--to=tim@brooklynpenguin.com \
--cc=git@vger.kernel.org \
--cc=johannes.schindelin@gmx.de \
--cc=vmiklos@frugalware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.