On Apr 17, 2007, at 10:42 AM, Jeffrey Ratcliffe wrote:

> On 17/04/07, muppet <[EMAIL PROTECTED]> wrote:
>> I couldn't reproduce that after tinkering for just a few moments,  
>> but i think
>> i see it in the code...
>
> Replace "one" with "twelve" twice, and during the second replacement,
> the error comes.
>
>> Any change to a TreeModel invalidates existing TreeIters.
>
>>> $cmp_model -> signal_connect('row-inserted' => sub {
>>>   my ($model, $path, $iter) = @_;
>>>   my ($val) = $cmp_model->get($iter, 0);
>>> warn "inserted $val\n";
>>>
>>> # Weed out duplicates
>>>   my $iter2 = $cmp_model->iter_next($iter);
>>>  while ($iter2) {
>>>   my ($val2) = $cmp_model->get($iter2, 0);
>>> warn "list $val2\n";
>>>   if ($val eq $val2) {
>>> warn "removing $val2\n";
>>>    $cmp_model->remove ($iter2);
>>> warn "removed $val2\n";
>
> I can add a return statement here, as there will only ever one
> duplicate, and then there are no problems with iters. But the error
> still comes.

I spent a few minutes running this code under gdb with the --g-fatal- 
warnings option...

The EntryCompletion uses a TreeModelFilter to narrow down the  
contents of the completion model to match what you've already typed.   
By the time we're doing that, the completion model is in a rather  
hosed state, and we get warnings about iters not being valid.   
Specifically, the iter's stamp does not match the model, which means  
that something Very Bad has happened.

The basic situation in which i've seen this happen before is  
modifying the model while iterating over it, which is exactly what  
your row-inserted handler is doing.  I can't pinpoint exactly *how*  
it is getting corrupted; it would take a lot of tracing and digging  
through unfamiliar code, since the error happens quite a way after  
the actual corruption occurs, and i'm just not up for that tonight.

On a hunch that the problem stems from modifying the completion model  
in a handler for a signal that is emitted when the model is  
modified...  i tried a slightly different approach.

Your code is unconditionally adding the user's text to the completion  
model, and then scraping out any duplicates.  Why let the duplicates  
in there in the first place?

I removed the entire row-inserted handler, and did this, instead:

   sub update_completion_model {
       my ($model, $new_value) = @_;
       # If not already in there, append.

       my $iter = $model->get_iter_first;
       while ($iter) {
           my $old_value = $model->get ($iter, 0);
           return if $old_value eq $new_value;
           $iter = $model->iter_next ($iter);
       }

       $model->insert_with_values (-1, 0, $new_value);
   }

   $slist -> get_model -> signal_connect('row-changed' => sub {
       my ($model, $path, $iter) = @_;
       my $text = $slist->get_model->get($iter, 0);
       update_completion_model ($cmp_model, $text);
   });


And i can no longer trigger the assertion failures.


--
If the monkey could type one keystroke every nanosecond, the expected  
waiting time until the monkey types out Hamlet is so long that the  
estimated age of the universe is insignificant by comparison ... this  
is not a practical method for writing plays.
   -- Gian-Carlo Rota


_______________________________________________
gtk-perl-list mailing list
gtk-perl-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-perl-list

Reply via email to