* gitk problems: can't unset "idinlist(...)"
@ 2007-07-20 23:05 Linus Torvalds
2007-07-21 5:09 ` Jeff King
2007-07-21 11:42 ` Paul Mackerras
0 siblings, 2 replies; 15+ messages in thread
From: Linus Torvalds @ 2007-07-20 23:05 UTC (permalink / raw)
To: Git Mailing List, Paul Mackerras; +Cc: Junio C Hamano
Ok, color me stumped, but gitk is unhappy.
Ingo and Thomas have just announced that they have a unified x86 tree for
both i386/x86-64, so I did
gitk arch/i386 arch/x86_64
to look at what has happened recently in the kernel in that area.
I get the gitk history view, but no actual diffs, and I get an application
error window saying
can't unset "idinlist(57d1c91fa6d9146b309b7511f6432dea2a24858b)": no such element in array
can't unset "idinlist(57d1c91fa6d9146b309b7511f6432dea2a24858b)": no such element in array
while executing
"unset idinlist($id)"
(procedure "layouttail" line 11)
invoked from within
"layouttail"
(procedure "layoutmore" line 35)
invoked from within
"layoutmore $tlimit $allread"
(procedure "chewcommits" line 9)
invoked from within
"chewcommits 1"
("eval" body line 1)
invoked from within
"eval $script"
(procedure "dorunq" line 9)
invoked from within
"dorunq"
("after" script)
which really doesn't tell me much.
It doesn't seem to happen without path limiting, and it also doesn't seem
to happen for all paths (doing "gitk drivers/scsi" doesn't show it), but
somehow that "arch/i386" part seems to bring it out.
I'm not seeing anything interesting or special about that named commit, or
anything else that would make gitk unhappy. But it is.
Current kernel tree. Anybody else has any ideas? Somebody who knows
tcl/tk, and gitk?
Linus
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-20 23:05 gitk problems: can't unset "idinlist(...)" Linus Torvalds
@ 2007-07-21 5:09 ` Jeff King
2007-07-21 5:53 ` Linus Torvalds
2007-07-21 11:42 ` Paul Mackerras
1 sibling, 1 reply; 15+ messages in thread
From: Jeff King @ 2007-07-21 5:09 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List, Paul Mackerras, Junio C Hamano
On Fri, Jul 20, 2007 at 04:05:54PM -0700, Linus Torvalds wrote:
> can't unset "idinlist(57d1c91fa6d9146b309b7511f6432dea2a24858b)": no such element in array
> [...]
> I'm not seeing anything interesting or special about that named commit, or
> anything else that would make gitk unhappy. But it is.
Interestingly, I repeatably get the exact same error but with a
different commit:
7ed40918a386afc2e14a6d3da563ea6d13686c25
which looks like a totally uninteresting commit.
I would expect, given that our repositories are at presumably the same
state, that we would get the same error at the same spot, but we don't.
Which implies to me there is some randomness, except that I get the
_same_ commit every time (and presumably so do you).
My master (and all other branches) are at c2e6805.
-Peff
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-21 5:09 ` Jeff King
@ 2007-07-21 5:53 ` Linus Torvalds
2007-07-21 5:56 ` Junio C Hamano
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Linus Torvalds @ 2007-07-21 5:53 UTC (permalink / raw)
To: Jeff King; +Cc: Git Mailing List, Paul Mackerras, Junio C Hamano
On Sat, 21 Jul 2007, Jeff King wrote:
>
> Interestingly, I repeatably get the exact same error but with a
> different commit:
>
> 7ed40918a386afc2e14a6d3da563ea6d13686c25
>
> which looks like a totally uninteresting commit.
It seems to depend on the path limiter.
With "arch/i386", I get the 7ed409 one, with "arch/i386 arch/x86_64" I get
a complaint about 57d1c91fa. In neither case do I see the reason.
But I think I found a clue. One thing special about that 57d1c91fa is that
when you do
git log --topo-order --parents --pretty=one arch/i386/ arch/x86_64/
and search for it, it first shows up as a parent for commit 9fdb62af92:
and not just _one_ parent, but three! So it looks like the parent
simplification is broken, and maybe gitk is unhappy for that reason.
The same is true of 7ed40918a38, btw, so yeah, I think that's it.
Junio, didn't we have some parent simplification patches recently?
Linus
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-21 5:53 ` Linus Torvalds
@ 2007-07-21 5:56 ` Junio C Hamano
2007-07-21 5:59 ` Jeff King
2007-07-21 6:11 ` Linus Torvalds
2 siblings, 0 replies; 15+ messages in thread
From: Junio C Hamano @ 2007-07-21 5:56 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Jeff King, Git Mailing List, Paul Mackerras
Linus Torvalds <torvalds@linux-foundation.org> writes:
> It seems to depend on the path limiter.
>
> With "arch/i386", I get the 7ed409 one, with "arch/i386 arch/x86_64" I get
> a complaint about 57d1c91fa. In neither case do I see the reason.
>
> But I think I found a clue. One thing special about that 57d1c91fa is that
> when you do
>
> git log --topo-order --parents --pretty=one arch/i386/ arch/x86_64/
>
> and search for it, it first shows up as a parent for commit 9fdb62af92:
> and not just _one_ parent, but three! So it looks like the parent
> simplification is broken, and maybe gitk is unhappy for that reason.
Yeah, I think if you limit the range at the bottom
(e.g. v2.6.21..) the problem disappears.
> The same is true of 7ed40918a38, btw, so yeah, I think that's it.
>
> Junio, didn't we have some parent simplification patches recently?
We had a patch to remove duplicated parent or something, I
think.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-21 5:53 ` Linus Torvalds
2007-07-21 5:56 ` Junio C Hamano
@ 2007-07-21 5:59 ` Jeff King
2007-07-21 6:06 ` Jeff King
2007-07-21 6:11 ` Linus Torvalds
2 siblings, 1 reply; 15+ messages in thread
From: Jeff King @ 2007-07-21 5:59 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List, Paul Mackerras, Junio C Hamano
On Fri, Jul 20, 2007 at 10:53:10PM -0700, Linus Torvalds wrote:
> With "arch/i386", I get the 7ed409 one, with "arch/i386 arch/x86_64" I get
> a complaint about 57d1c91fa. In neither case do I see the reason.
Oops, I thought you were using a different command line.
> git log --topo-order --parents --pretty=one arch/i386/ arch/x86_64/
>
> and search for it, it first shows up as a parent for commit 9fdb62af92:
> and not just _one_ parent, but three! So it looks like the parent
> simplification is broken, and maybe gitk is unhappy for that reason.
OK, that should make it easier to find (note also that 9fdb62af92 is an
octopus, which might be related).
> Junio, didn't we have some parent simplification patches recently?
v1.5.2 works, so I am bisecting.
-Peff
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-21 5:59 ` Jeff King
@ 2007-07-21 6:06 ` Jeff King
0 siblings, 0 replies; 15+ messages in thread
From: Jeff King @ 2007-07-21 6:06 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List, Paul Mackerras, Junio C Hamano
On Sat, Jul 21, 2007 at 01:59:18AM -0400, Jeff King wrote:
> v1.5.2 works, so I am bisecting.
Hmm. The bad commit is 1ed84157. The commit message is a very suspicious
"Revert 88494423 (removal of duplicate parents in the output codepath)."
-Peff
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-21 5:53 ` Linus Torvalds
2007-07-21 5:56 ` Junio C Hamano
2007-07-21 5:59 ` Jeff King
@ 2007-07-21 6:11 ` Linus Torvalds
2007-07-21 6:18 ` Jeff King
2 siblings, 1 reply; 15+ messages in thread
From: Linus Torvalds @ 2007-07-21 6:11 UTC (permalink / raw)
To: Jeff King; +Cc: Git Mailing List, Paul Mackerras, Junio C Hamano
On Fri, 20 Jul 2007, Linus Torvalds wrote:
>
> Junio, didn't we have some parent simplification patches recently?
Yeah. Junio, I think your 11d6596709e04b8d2b429f230b2ed570d013f812 is
buggy.
Here's a patch. Not very well tested, but it makes gitk happy and passes
all the tests. And I really think Junio's code was very dubious (it did
that "p = p->next" *every* time, and then did "pp = &p->next", so "pp"
would end up jumping by multiple entries.
The new code only ever changes "pp" - either by moving p->next into it
(delete the current entry) or by moving pp forward by one (keep the
current entry).
That's much more logical, but somebody should double-check me anyway.
Linus
---
Subject: Fix up duplicate parents removal
This removes duplicate parents properly, making gitk happy again.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
revision.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/revision.c b/revision.c
index 28b5f2e..7036cf2 100644
--- a/revision.c
+++ b/revision.c
@@ -1323,16 +1323,17 @@ static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp
static void remove_duplicate_parents(struct commit *commit)
{
- struct commit_list *p;
- struct commit_list **pp = &commit->parents;
+ struct commit_list **pp, *p;
/* Examine existing parents while marking ones we have seen... */
- for (p = commit->parents; p; p = p->next) {
+ pp = &commit->parents;
+ while ((p = *pp) != NULL) {
struct commit *parent = p->item;
- if (parent->object.flags & TMP_MARK)
+ if (parent->object.flags & TMP_MARK) {
+ *pp = p->next;
continue;
+ }
parent->object.flags |= TMP_MARK;
- *pp = p;
pp = &p->next;
}
/* ... and clear the temporary mark */
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-21 6:11 ` Linus Torvalds
@ 2007-07-21 6:18 ` Jeff King
2007-07-21 6:24 ` Jeff King
2007-07-21 6:34 ` gitk problems: can't unset "idinlist(...)" Linus Torvalds
0 siblings, 2 replies; 15+ messages in thread
From: Jeff King @ 2007-07-21 6:18 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List, Paul Mackerras, Junio C Hamano
On Fri, Jul 20, 2007 at 11:11:19PM -0700, Linus Torvalds wrote:
> Here's a patch. Not very well tested, but it makes gitk happy and passes
> all the tests. And I really think Junio's code was very dubious (it did
> that "p = p->next" *every* time, and then did "pp = &p->next", so "pp"
> would end up jumping by multiple entries.
I just independently came to the same conclusion. Your patch looks
correct to me (though there are some unrelated formatting changes which
made it a little harder to read).
Acked-by: Jeff King <peff@peff.net>
-Peff
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-21 6:18 ` Jeff King
@ 2007-07-21 6:24 ` Jeff King
2007-07-21 6:47 ` Linus Torvalds
2007-07-21 6:34 ` gitk problems: can't unset "idinlist(...)" Linus Torvalds
1 sibling, 1 reply; 15+ messages in thread
From: Jeff King @ 2007-07-21 6:24 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List, Paul Mackerras, Junio C Hamano
On Sat, Jul 21, 2007 at 02:18:57AM -0400, Jeff King wrote:
> correct to me (though there are some unrelated formatting changes which
> made it a little harder to read).
By which I mean you can keep the 'for' loop, since in either case we are
always reading p->next (if we skip, then we set *pp to p->next anyway,
and if we don't, then pp becomes a pointer to p->next).
So this is a more readable patch which I believe is equivalent.
---
diff --git a/revision.c b/revision.c
index 28b5f2e..7def867 100644
--- a/revision.c
+++ b/revision.c
@@ -1329,10 +1329,11 @@ static void remove_duplicate_parents(struct commit *commit)
/* Examine existing parents while marking ones we have seen... */
for (p = commit->parents; p; p = p->next) {
struct commit *parent = p->item;
- if (parent->object.flags & TMP_MARK)
+ if (parent->object.flags & TMP_MARK) {
+ *pp = p->next;
continue;
+ }
parent->object.flags |= TMP_MARK;
- *pp = p;
pp = &p->next;
}
/* ... and clear the temporary mark */
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-21 6:18 ` Jeff King
2007-07-21 6:24 ` Jeff King
@ 2007-07-21 6:34 ` Linus Torvalds
1 sibling, 0 replies; 15+ messages in thread
From: Linus Torvalds @ 2007-07-21 6:34 UTC (permalink / raw)
To: Jeff King; +Cc: Git Mailing List, Paul Mackerras, Junio C Hamano
On Sat, 21 Jul 2007, Jeff King wrote:
>
> I just independently came to the same conclusion. Your patch looks
> correct to me (though there are some unrelated formatting changes which
> made it a little harder to read).
Yeah, I shouldn't have done that - I just ended up changing the "for()" to
a "while()" (because we should *not* do the same thing at the end of the
loop each time). And as a part of that I changed the initialization to be
at the head of the while-loop rather than in the variable declaration,
because that's how I tend to mostly write while-loops.
But I probably should have tried to keep the patch minimal instead, so
that it would show the changes better. Probably not a big deal.
Linus
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-21 6:24 ` Jeff King
@ 2007-07-21 6:47 ` Linus Torvalds
2007-07-21 6:54 ` Jeff King
2007-07-21 9:32 ` pointer to pointer (was: gitk problems: can't unset "idinlist(...)") David Kastrup
0 siblings, 2 replies; 15+ messages in thread
From: Linus Torvalds @ 2007-07-21 6:47 UTC (permalink / raw)
To: Jeff King; +Cc: Git Mailing List, Paul Mackerras, Junio C Hamano
On Sat, 21 Jul 2007, Jeff King wrote:
>
> By which I mean you can keep the 'for' loop, since in either case we are
> always reading p->next (if we skip, then we set *pp to p->next anyway,
> and if we don't, then pp becomes a pointer to p->next).
>
> So this is a more readable patch which I believe is equivalent.
Fair enough, that also works.
Anyway, just because this is actually something I've noticed a lot of
people do wrong, I actually do tend to think that when you traverse a
singly-linked list and remove entries, you should *never* traverse the
list itself, you should only ever traverse the "pointer to the pointer".
So the difference between your version and mine is that the
while ((p = *pp) != NULL)
model really only has one single "iterator variable": "pp". Which makes it
a lot easier to think about and avoid problems.
In contrast, your for-loop actually keeps track of *two* independent
variables, the "tail pointer of the list we're building up" (pp) and the
"head pointer of the old list we're traversing" (p).
Does it work? Yes. But I tend to prefer the "there's a single list" model,
where you just remove entries as you traverse it through a single indirect
pointer.
They're certainly equivalent, but slightly different mindsets. I at least
personally find the "single pointer" less likely to have problems, because
you can never get out of sync (which was basically exactly the problem
that Junio's code had), because there is nothing to get out of sync _with_
when you just have a single main iterator variable.
Linus
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-21 6:47 ` Linus Torvalds
@ 2007-07-21 6:54 ` Jeff King
2007-07-21 9:32 ` pointer to pointer (was: gitk problems: can't unset "idinlist(...)") David Kastrup
1 sibling, 0 replies; 15+ messages in thread
From: Jeff King @ 2007-07-21 6:54 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List, Paul Mackerras, Junio C Hamano
On Fri, Jul 20, 2007 at 11:47:24PM -0700, Linus Torvalds wrote:
> So the difference between your version and mine is that the
>
> while ((p = *pp) != NULL)
I actually like your version better (I like saving for loops for
honest-to-god, for-each-element-in-this-list iteration; munging the list
in the middle is something that you _should_ call attention to). I just
found your patch much harder to verify, because I had to make sure the
for/while change was equivalent. So you can blame Junio for writing it
wrong in the first place. :)
Junio, whatever you apply, please credit Linus; he beat me to the fix
and so my patch is completely cribbed from his. :)
-Peff
^ permalink raw reply [flat|nested] 15+ messages in thread
* pointer to pointer (was: gitk problems: can't unset "idinlist(...)")
2007-07-21 6:47 ` Linus Torvalds
2007-07-21 6:54 ` Jeff King
@ 2007-07-21 9:32 ` David Kastrup
2007-07-21 9:44 ` pointer to pointer David Kastrup
1 sibling, 1 reply; 15+ messages in thread
From: David Kastrup @ 2007-07-21 9:32 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 1445 bytes --]
Linus Torvalds <torvalds@linux-foundation.org> writes:
> Anyway, just because this is actually something I've noticed a lot
> of people do wrong, I actually do tend to think that when you
> traverse a singly-linked list and remove entries, you should *never*
> traverse the list itself, you should only ever traverse the "pointer
> to the pointer".
When I have doubly-linked lists where there is only forward traversal
(the backlink being for convenient deletions without context), I make
the backlink a pointer to pointer. This also means that one can
remove at the front of the list without needing to know the head
separately.
Anyway, here is some really, really ancient code of mine (file date is
of 1990 but it's older than that) which sorts linked lists stably
without extra storage and makes heavy use of pointer to pointer
traversal in both code and interface. There is also a strictly
non-recursive variant with the same data flow (except for never making
a redundant assignment) and just one instead of two functions which
consistently beats good qsort implementations, but this old version is
quite more fun to read.
Basically, if head is the pointer to a sorted list of at least n
elements, mergesort(&head, n) will sort the first n elements and
return a pointer to that link which contains the tail of the list. So
if you did not already 0-terminate your list, *mergesort(&head,n)=0;
will both sort and terminate your list.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Stable Mergesort on linked lists --]
[-- Type: text/x-csrc, Size: 1007 bytes --]
#include "mergesrt.h"
int (*mergecompare)(void *p1, void *p2);
int mergelink;
#define getlink(adr) (*(void**)((char*)(adr)+mergelink))
static void **merge(void **head1, void **tail1, void **tail2, unsigned n1, unsigned n2)
{
register void *p1 = *head1, *p2 = *tail1;
for(;;) {
if ((*mergecompare)(p1, p2) <= 0) {
p1 = *(head1 = &getlink(*head1 = p1));
if (--n1 == 0)
return *head1 = p2, tail2;
} else {
p2 = *(head1 = &getlink(*head1 = p2));
if (--n2 == 0)
return *tail1 = p2, *head1 = p1, tail1;
}
}
}
void **mergesort(void **head, unsigned n)
{
switch (n) {
case 0:
return head;
case 1:
return &getlink(*head);
case 2:
{
register void *p1, *p2;
p2 = getlink(p1 = *head);
if ((*mergecompare)(p1, p2) <= 0)
return &getlink(p2);
getlink(p1) = getlink(*head=p2);
return &getlink(getlink(p2) = p1);
}
default:
{
unsigned m;
void **h2;
n -= m = n / 2;
h2 = mergesort(head, n);
return merge(head,h2,mergesort(h2,m),n,m);
}
}
}
[-- Attachment #3: Type: text/plain, Size: 52 bytes --]
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: pointer to pointer
2007-07-21 9:32 ` pointer to pointer (was: gitk problems: can't unset "idinlist(...)") David Kastrup
@ 2007-07-21 9:44 ` David Kastrup
0 siblings, 0 replies; 15+ messages in thread
From: David Kastrup @ 2007-07-21 9:44 UTC (permalink / raw)
To: git
David Kastrup <dak@gnu.org> writes:
Content-Type: text/x-csrc
Content-Disposition: attachment
Content-Description: Stable Mergesort on linked lists
Sorry, this was supposed to be inline. I apologize for the
inconvenience.
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: gitk problems: can't unset "idinlist(...)"
2007-07-20 23:05 gitk problems: can't unset "idinlist(...)" Linus Torvalds
2007-07-21 5:09 ` Jeff King
@ 2007-07-21 11:42 ` Paul Mackerras
1 sibling, 0 replies; 15+ messages in thread
From: Paul Mackerras @ 2007-07-21 11:42 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List, Junio C Hamano
Linus Torvalds writes:
> Somebody who knows
> tcl/tk, and gitk?
That sounds like me. :) I see from the following messages that the
bug turned out to be elsewhere in git, but it looks like gitk should
be more robust and do something sensible rather than just throwing a
Tcl error. I'll look at it.
Paul.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2007-07-21 11:42 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-20 23:05 gitk problems: can't unset "idinlist(...)" Linus Torvalds
2007-07-21 5:09 ` Jeff King
2007-07-21 5:53 ` Linus Torvalds
2007-07-21 5:56 ` Junio C Hamano
2007-07-21 5:59 ` Jeff King
2007-07-21 6:06 ` Jeff King
2007-07-21 6:11 ` Linus Torvalds
2007-07-21 6:18 ` Jeff King
2007-07-21 6:24 ` Jeff King
2007-07-21 6:47 ` Linus Torvalds
2007-07-21 6:54 ` Jeff King
2007-07-21 9:32 ` pointer to pointer (was: gitk problems: can't unset "idinlist(...)") David Kastrup
2007-07-21 9:44 ` pointer to pointer David Kastrup
2007-07-21 6:34 ` gitk problems: can't unset "idinlist(...)" Linus Torvalds
2007-07-21 11:42 ` Paul Mackerras
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox