On Wed, Sep 10, 2008 at 6:26 PM, Bram Moolenaar <[EMAIL PROTECTED]> wrote:
>
> Dominique Pelle wrote:
>
>> On Fri, Aug 22, 2008 at 3:32 AM, Matt Wozniski wrote:
>>
>> > Not sure what's going on here, but I've found a crash that's easy to
>> > reproduce.  First, open two X11 enabled vim (not gvim) processes.  In
>> > the first, do:
>> > :let @+ = repeat('a', 1024*1024)
>> > in order to store 1MB of data to the clipboard.  The exact amount is
>> > irrelevant, but the larger the size, the more often it will lead to a
>> > segfault.
>> >
>> > Then, in the second vim instance, repeatedly do ":reg +" and see what
>> > gets displayed.  Depending upon the amount of data that you put on the
>> > clipboard, as well as upon some other factor I'm not seeing, this will
>> > either a) show a bunch of a's in register +, b) not show any
>> > registers, as though register + didn't exist, or c) cause the vim in
>> > which you copied to segfault, and the vim in which you're trying to
>> > display the register to enter a tight loop wasting a lot of CPU and
>> > only dying for kill -9.  Just try the command 5 or so times and you
>> > should see a segfault - as well as the missing-register behavior.  If
>> > you don't get the segfault at all, try upping the amount of data
>> > stored to the clipboard.  If you get the segfault, but not the
>> > missing-register behavior, try lowering the amount of data stored to
>> > the clipboard.  And if you can't reproduce either, that might help to
>> > pin down what exactly causes this.
>> >
>> > I can reproduce this on both a vim linked with the GTK2-Gnome gui, and
>> > one linked with the X11-Motif gui, so it doesn't seem to be something
>> > gnome-specific, either.  This is vim 7.2.
>> >
>> > Let me know if we need more details.
>> >
>> > ~Matt
>>
>>
>> It does not seem easy to debug.  I think there might
>> be 2 distinct issues.
>>
>> 1/ The first thing I notice and which seems to be 100% reproducible
>> on my machine):
>>
>> In #1 instance of vim:   :let @+ = repeat('a', 262033)
>> In #2 instance of vim:    :reg+    (works fine all the time)
>>
>> In #1 instance of vim:   :let @+ = repeat('b', 262034)
>> In #2 instance of vim:    :reg+    (fails all the time, it shows empty 
>> content)
>>
>> clip_x11_request_selection_cb() fails in #2 instance of vim
>> because parameter value is NULL and  parameter *length is null.
>>
>> Somehow it happens when number of characters in clipboard
>> is >= 262034 (close to 256K).
>>
>> I change the letter ('a' -> 'b') in the clipboard every time to make
>> sure ":reg +" does not show an old value of the clipboard (which
>> I have observed sometimes, see below)
>>
>>
>> 2/ The second thing I notice, if I put far more characters in the
>> clipboard (say 1000000) then if fails differently:
>>
>> In #1 instance of vim:   :let @+ = repeat('c', 1000*1000)
>> In #2 instance of vim:    :reg+    (fails, it shows some incorrect
>> content, something which I happened copy earlier "33333...."?!)
>>
>> So with such a big clipboard content, it fails differently:
>> In instance #2 of vim, function clip_x11_request_selection()
>> retries 5 times until it falls back to calling clip_yank_selection(),
>> but somehow that does not work either.
>>
>> If both instances are gvim rather than vim, then I do not see
>> any problem.
>>
>> I have not been able to come up with a fix yet.
>
> I have a fix, but I'm not sure if this fixes all the problems:
>
> *** ../vim-7.2.014/src/ui.c     Sun Sep  7 21:47:51 2008
> --- src/ui.c    Wed Sep 10 18:05:37 2008
> ***************
> *** 2076,2082 ****
>        text_prop.value = (unsigned char *)value;
>        text_prop.encoding = *type;
>        text_prop.format = *format;
> !       text_prop.nitems = STRLEN(value);
>        status = XmbTextPropertyToTextList(X_DISPLAY, &text_prop,
>                                                         &text_list, &n_text);
>        if (status != Success || n_text < 1)
> --- 2076,2082 ----
>        text_prop.value = (unsigned char *)value;
>        text_prop.encoding = *type;
>        text_prop.format = *format;
> !       text_prop.nitems = len;
>        status = XmbTextPropertyToTextList(X_DISPLAY, &text_prop,
>                                                         &text_list, &n_text);
>        if (status != Success || n_text < 1)
>
> Please give this a try in your environment.  This should fix the problem
> with reading beyond allocated memory.  For me it does not appear to fix
> the problem with pasting lots of 'b' characters.  For me the limit is
> 262041.  So there appears to be a maximum size for the clipboard.


Yes, that fixes the valgrind error, but it does not fix the pasting
bug for me either.  Another way to fix the valgrind error was to
copy the end of string into the buffer.

One thing I noticed, there seems to be a race condition.

In ui.c, I see:

2153                 /* this is where clip_x11_request_selection_cb()
is actually
2154                  * called */
2155                 XtDispatchEvent(&event);

Well, the comment does not seem to be true.  The callback may
sometimes be called later (and before we test for its success).

I did the following experiment, I initialized 'success' to -1 (rather than
FALSE) so I can know for sure whether clip_x11_request_selection_cb()
has been called (since it sets success to TRUE (1) or FALSE (0).
At the point where we test for success, sometimes it's still -1  (meaning
that callback has not been called).  If I wait a little, then I see it being
called.  The attached patch (just for experimentation purpose)
illustrates what I'm talking about.

With this patch, if I do:

:let @+ = repeat('b', 340000)

and in the second vim:

:reg +

... and then I see...

*** waited for success!!! success=0 try=20

... meaning that the callback was not called yet when testing
success initially, but but gets called shortly after, after doing
just one sleep of 50ms.  It does not make paste work better
unfortunately but it shows a possible problem which might be
a timing issue.

I read the man page of XtGetSelectionValue() but it is not clear
when the callback is mean to be called.  It merely says:

   The specified callback will be called some
   time after XtGetSelectionValue is called; in
   fact, it may be called before or after
   XtGetSelectionValue returns.

-- Dominique

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Index: ui.c
===================================================================
RCS file: /cvsroot/vim/vim7/src/ui.c,v
retrieving revision 1.32
diff -c -r1.32 ui.c
*** ui.c	7 Sep 2008 19:48:35 -0000	1.32
--- ui.c	10 Sep 2008 18:26:22 -0000
***************
*** 2076,2082 ****
  	text_prop.value = (unsigned char *)value;
  	text_prop.encoding = *type;
  	text_prop.format = *format;
! 	text_prop.nitems = STRLEN(value);
  	status = XmbTextPropertyToTextList(X_DISPLAY, &text_prop,
  							 &text_list, &n_text);
  	if (status != Success || n_text < 1)
--- 2076,2082 ----
  	text_prop.value = (unsigned char *)value;
  	text_prop.encoding = *type;
  	text_prop.format = *format;
! 	text_prop.nitems = len;
  	status = XmbTextPropertyToTextList(X_DISPLAY, &text_prop,
  							 &text_list, &n_text);
  	if (status != Success || n_text < 1)
***************
*** 2131,2137 ****
  	    case 3:  type = text_atom;		break;
  	    default: type = XA_STRING;
  	}
! 	success = FALSE;
  	XtGetSelectionValue(myShell, cbd->sel_atom, type,
  	    clip_x11_request_selection_cb, (XtPointer)&success, CurrentTime);
  
--- 2131,2138 ----
  	    case 3:  type = text_atom;		break;
  	    default: type = XA_STRING;
  	}
! 	success = -1;  /* < 0 when callback not called yet, callback 
!                         * will set it to TRUE or FALSE */
  	XtGetSelectionValue(myShell, cbd->sel_atom, type,
  	    clip_x11_request_selection_cb, (XtPointer)&success, CurrentTime);
  
***************
*** 2177,2183 ****
  	    ui_delay(1L, TRUE);
  	}
  
! 	if (success)
  	    return;
  
  	/* don't do a retry with another type after timing out, otherwise we
--- 2178,2197 ----
  	    ui_delay(1L, TRUE);
  	}
  
!         if (success < 0) 
!         {
!             /* Strange: callback has not been called yet!?  Wait a bit
!              * for it to be called. */
!             int try = 20;
!             do
!                 mch_delay(50L, FALSE); /* sleep 50 ms */
!             while (success < 0 && --try);
!             fprintf(stderr,
!                     "*** waited for success!!! success=%d try=%d\n",
!                     success, try);
!         }
! 
! 	if (success == TRUE)
  	    return;
  
  	/* don't do a retry with another type after timing out, otherwise we

Raspunde prin e-mail lui