<br><br><div class="gmail_quote">On Wed, Mar 10, 2010 at 6:39 AM, Jon Hylands <span dir="ltr"><<a href="mailto:jon@huv.com">jon@huv.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">On Fri, 19 Feb 2010 16:25:20 -0500, Jon Hylands <<a href="mailto:jon@huv.com">jon@huv.com</a>> wrote:<br>
<br>
>I'm getting a weird problem, and its been so many years since I saw<br>
>this, I'm at a loss as to what to do...<br>
><br>
>On my robot Brainbot, I have a 2.83 GHz Core 2 Quad with 2 GB RAM and<br>
>a 32 GB solid state HD. It is running Windows XP Pro.<br>
><br>
>I'm getting a Low Space Notifier whenever I try and copy text to the<br>
>clipboard, or when I try and paste. I can do other development things,<br>
>writing a saving code, and opening browsers and windows with no<br>
>problems.<br>
><br>
>Task Manager says Squeak is taking up 37,980 K, and the machine has<br>
>1.2 GB of free physical memory.<br>
><br>
>I'm running the following VM:<br>
><br>
>Squeak 3.10.6 (release) from Aug 30 2007<br>
><br>
>And the following image:<br>
><br>
>Squeak 3.10.2<br>
>latest update: #7179<br>
<br>
</div>Okay, so this is still bothering me, and I dug a little deeper, and<br>
came across something that blew me away...<br>
<br>
<a href="http://www.huv.com/Clipboard-OutOfMemory.png" target="_blank">http://www.huv.com/Clipboard-OutOfMemory.png</a><br>
<br>
Basically, when I do 'copy', the primitive returns a ByteString that<br>
is 4 billion bytes long -- 2^32 - 1 to be exact. Clearly that is not<br>
really allocated, because even when I have this inspector open, Squeak<br>
is still only taking about 37 MB of memory.<br>
<br>
However, the method String >> #withSqueakLineEndings is trying to<br>
create a new string that is 4 billion bytes long, and that is where I<br>
run into the low space warning.<br>
<br>
Primitive 141 appears to be causing the issue.<br></blockquote><div><br></div><div>The primitive looks like this in my quite possibly obsolete VM sources:</div><div><br></div><div>primitiveClipboardText</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>"When called with a single string argument, post the string to </div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>the clipboard. When called with zero arguments, return a </div><div><span class="Apple-tab-span" style="white-space:pre">        </span>string containing the current clipboard contents."</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>| s sz |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>argumentCount = 1</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [s := self stackTop.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>(self isBytes: s) ifFalse: [^ self primitiveFail].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self successful</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [sz := self stSizeOf: s.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span>self clipboardWrite: sz From: s + BaseHeaderSize At: 0.</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>self pop: 1]]</div><div>
<span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: [sz := self clipboardSize.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>(self sufficientSpaceToAllocate: sz) ifFalse:[^self primitiveFail].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>s := self instantiateClass: (self splObj: ClassString) indexableSize: sz.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self clipboardRead: sz Into: s + BaseHeaderSize At: 0.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>self pop: 1 thenPush: s]</div><div><br></div><div>I'm willing to bet that clipboardSize is returning -1.</div><div><br></div><div>It probably needs to read something like</div>
<div><br></div><div>primitiveClipboardText</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>"When called with a single string argument, post the string to </div><div><span class="Apple-tab-span" style="white-space:pre">        </span>the clipboard. When called with zero arguments, return a </div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>string containing the current clipboard contents."</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| s sz |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>argumentCount = 1</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [s := self stackTop.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>(self isBytes: s) ifFalse: [^ self primitiveFail].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>self successful</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [sz := self stSizeOf: s.</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>self clipboardWrite: sz From: s + BaseHeaderSize At: 0.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span>self pop: 1]]</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: [sz := self clipboardSize.</div><div>>><span class="Apple-tab-span" style="white-space:pre">                        </span>(sz >= 0 and: [self sufficientSpaceToAllocate: sz]) ifFalse:[^self primitiveFail].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>s := self instantiateClass: (self splObj: ClassString) indexableSize: sz.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self clipboardRead: sz Into: s + BaseHeaderSize At: 0.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>self pop: 1 thenPush: s] </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
I'm not much of a VM person, so hopefully someone who is can look at<br>
that primitive and figure out what case is causing it.<br>
<br>
One more thing to note - I'm running Windows in a Remote Desktop, from<br>
a Linux machine. To clarify, my development machine is a desktop,<br>
running Ubuntu linux. The robot is a mini-itx running Windows XP Pro.<br>
I use remote desktop from linux to access the Windows GUI on the<br>
robot.<br></blockquote><div><br></div><div>The Windows VM's clipboardText function is a tad unsafe:</div><div><br></div><div>int clipboardSize(void) {</div><div> HANDLE h;</div><div> WCHAR *src;</div><div> unsigned char *tmp;</div>
<div> int i, count, bytesNeeded;</div><div><br></div><div> /* Do we have text in the clipboard? */</div><div> if(!IsClipboardFormatAvailable(CF_UNICODETEXT))</div><div> return 0;</div><div><br></div><div> if(!OpenClipboard(stWindow))</div>
<div> return 0;</div><div><br></div><div> /* Get it in unicode format. */</div><div> h = GetClipboardData(CF_UNICODETEXT);</div><div> src = GlobalLock(h);</div><div><br></div><div> /* How many bytes do we need to store those unicode chars in UTF8 format? */</div>
<div> bytesNeeded = WideCharToMultiByte(CP_UTF8, 0, src, -1,</div><div> NULL, 0, NULL, NULL );</div><div> tmp = malloc(bytesNeeded+1);</div><div><br></div><div> /* Convert Unicode text to UTF8. */</div>
<div> WideCharToMultiByte(CP_UTF8, 0, src, -1, tmp, bytesNeeded , NULL, NULL);</div><div><br></div><div> /* Count CrLfs for which we remove the extra Lf */</div><div> count = bytesNeeded; /* ex. terminating zero */</div>
<div> for(i=0; i<count; i++) {</div><div> if((tmp[i] == 13) && (tmp[i+1] == 10)) bytesNeeded--;</div><div> }</div><div> bytesNeeded--; /* discount terminating zero */</div><div> free(tmp); /* no longer needed */</div>
<div><br></div><div> GlobalUnlock(h);</div><div> CloseClipboard();</div><div><br></div><div> return bytesNeeded;</div><div>}</div><div><br></div><div>If bytesNeeded is zero then the function will return (int)-1. </div>
<div><br></div><div>From the MS manual page:</div><div><br></div><div><span class="Apple-style-span" style="font-family: 'Segoe UI', Verdana, Arial; font-size: 12px; "><h3 style="font-family: 'Segoe UI', Verdana, Arial; font-size: 1.1666em; color: rgb(63, 82, 156); font-weight: bold; ">
Return Value</h3><p>Returns the number of bytes written to the buffer pointed to by <em>lpMultiByteStr</em> if successful. If the function succeeds and <em>cbMultiByte</em> is 0, the return value is the required size, in bytes, for the buffer indicated by <em>lpMultiByteStr</em>.</p>
<p>The function returns 0 if it does not succeed. To get extended error information, the application can call <strong>GetLastError</strong>, which can return one of the following error codes:</p><ul><li>ERROR_INSUFFICIENT_BUFFER. A supplied buffer size was not large enough, or it was incorrectly set to NULL.</li>
<li>ERROR_INVALID_FLAGS. The values supplied for flags were not valid.</li><li>ERROR_INVALID_PARAMETER. Any of the parameter values was invalid.</li><li>ERROR_NO_UNICODE_TRANSLATION. Invalid Unicode was found in a string.</li>
</ul><div><br></div><div><span class="Apple-style-span" style="font-family: arial; font-size: small; "><div>So something like</div><div><br></div><div><span class="Apple-style-span" style="font-family: arial; "><div> /* How many bytes do we need to store those unicode chars in UTF8 format? */</div>
<div> bytesNeeded = WideCharToMultiByte(CP_UTF8, 0, src, -1,</div><div> NULL, 0, NULL, NULL );</div><div> if (bytesNeeded <= 0)</div><div> return 0;</div><div><br></div><div>would be wise.</div>
<div> </div></span></div></span></div></span></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
Later,<br>
<font color="#888888">Jon<br>
<br>
<br>
</font></blockquote></div><br>