All of lore.kernel.org
 help / color / mirror / Atom feed
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

  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.