<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Your Catchphrase Here! &#187; Tech</title>
	<atom:link href="http://blog.christopherschultz.net/index.php/category/Tech/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.christopherschultz.net</link>
	<description>Rantings of a Lunatic</description>
	<lastBuildDate>Tue, 31 Aug 2010 19:07:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Trapped DVD after a failed Snow Leopard Install on a Mac Mini</title>
		<link>http://blog.christopherschultz.net/index.php/2009/12/02/trapped-dvd-after-a-failed-snow-leopard-install-on-a-mac-mini/</link>
		<comments>http://blog.christopherschultz.net/index.php/2009/12/02/trapped-dvd-after-a-failed-snow-leopard-install-on-a-mac-mini/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 15:31:38 +0000</pubDate>
		<dc:creator>Christopher</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.christopherschultz.net/?p=80</guid>
		<description><![CDATA[I have an Intel-based Mac Mini running Mac OS X Tiger that I tried to upgrade to Snow Leopard. After a failed install (not enough memory), the DVD stayed in the drive and, after the reboot, the whole process repeated. I was able to get the DVD out! Read on for details...]]></description>
			<content:encoded><![CDATA[<p>Yeah, that&#8217;s a long title, but I want it to be easily searchable on the web.</p>
<p>I have an Intel-based Mac Mini running <a href="http://en.wikipedia.org/wiki/Mac_os_x">Mac OS X</a> Tiger. I recently procured a <a href="http://en.wikipedia.org/wiki/Mac_OS_X_Snow_Leopard">Snow Leopard</a> DVD and read that you can, in fact, upgrade from Tiger to Snow Leopard. Snow Leopard has some cool new features that I thought I&#8217;d like, so I gave it a shot.</p>
<p>I inserted the DVD and the finder window came up showing me the &#8220;Install Mac OS X&#8221; option and I double-clicked on it. It told me it had to reboot in order to perform the installation, so I said okay and it rebooted.</p>
<p><em>(Note that I didn&#8217;t care what happened to my existing installation, files, etc&#8230; this machine is used for web application testing, so I don&#8217;t care if I wipe everything or not).</em></p>
<p>After a few minutes, the installer came up and asked me what language I wanted to use (English) and I continued the install. It thought about things for a while and then told me:</p>
<blockquote><p>Mac OS X cannot be installed on this machine because it does not have enough memory.</p></blockquote>
<p>My options at this point were: <em>Restore from Backup</em> and <em>Reboot</em>. I chose the latter, thinking that the DVD would eject and I&#8217;d be back to using my old Tiger install.</p>
<p>Instead, the DVD stayed in the drive and, after the reboot, the whole process repeated &#8212; basically, I was asked what language I wanted and then told that my computer didn&#8217;t have enough memory to install Snow Leopard. :(</p>
<p>So, I tried the most obvious thing any Mac user would do: I pressed the <em>eject</em> button on the keyboard. No dice. I held the eject button down for what must have been 2 minutes. Nothing.</p>
<p>I tried Googling for answers. Lots of people giving various suggestions, none of which was working for me. CTRL-COMMAND-O-F apparently doesn&#8217;t work on Intel Macs. Holding OPTION during boot did nothing. Holding EJECT did nothing. Holding the mouse button down did nothing. I was seriously contemplating cracking open the machine to extract the DVD.</p>
<p>Someone suggested plugging the mouse button directly into the Mac, because some USB hubs don&#8217;t work quite right at initial boot. I have a Mac keyboard with my mouse plugged directly into that. That&#8217;s about as directly-plugged as you can get, right?</p>
<p>Well, apparently not. I moved by USB mouse from the keyboard to the back of the Mac Mini and held down the mouse during boot. <em>Voile!</em> Out popped the DVD.</p>
<p>So, anyone having similar problems can try this trick. It may save you from tearing-open your Mac Mini, or tearing-out your hair.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.christopherschultz.net/index.php/2009/12/02/trapped-dvd-after-a-failed-snow-leopard-install-on-a-mac-mini/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Properly Handling Pooled JDBC Connections</title>
		<link>http://blog.christopherschultz.net/index.php/2009/03/16/properly-handling-pooled-jdbc-connections/</link>
		<comments>http://blog.christopherschultz.net/index.php/2009/03/16/properly-handling-pooled-jdbc-connections/#comments</comments>
		<pubDate>Mon, 16 Mar 2009 22:46:44 +0000</pubDate>
		<dc:creator>Christopher</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.christopherschultz.net/?p=68</guid>
		<description><![CDATA[I&#8217;m an active member of the Tomcat-users mailing list and I see lots of folks that post questions about not being able to get a new database connection. The answer is simple: you have exhausted their JDBC connection pool. The answer is not so simple because the reasons for the situation can often be different, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m an active member of the <a title="Apache Tomcat Mailing Lists" href="http://tomcat.apache.org/lists.html">Tomcat-users</a> mailing list and I see lots of folks that post questions about not being able to get a new database connection. The answer is simple: you have exhausted their JDBC connection pool. The answer is not so simple because the reasons for the situation can often be different, but most likely, your application is not properly handing pooled connections. Read on for information on how to code your app to properly handle such pooled connections.</p>
<p><span id="more-68"></span></p>
<p>I won&#8217;t go on and on about what a good idea connection pools are. That is either self-evident or covered elsewhere. What is <em>not</em> properly covered elsewhere is how to write your code correctly. They&#8217;re all throwaway examples that work under the best circumstances but fall apart when anything goes wrong.</p>
<p>When using a pooled connection, the idea is that you shouldn&#8217;t have to go out of your way to treat it specially. Technically, the techniques shown in this post are not just useful for pooled connections: it&#8217;s simply how you <em>should</em> code JDBC interactions, pooled or otherwise. The basics are simply: acquire your connection, and make sure you close everything before your method completes. Unfortunately, folks often forget that exceptions can be thrown and your cleanup code might not actually get called.</p>
<p>Below are two annotated code samples that should demonstrate everything you should be doing when handling JDBC connections. I hope this helps some folks out there.</p>
<p>The first code snippet is for when you are not engaging in a SQL transaction. Sure, you <em>could</em> use the transactional code in all cases, but the non-transactional one is simpler and will make your code easier to read and understand. It also won&#8217;t give you any &#8220;cannot rollback connection that isn&#8217;t in a transaction&#8221; errors. My code throws application-specific exceptions to demonstrate how to shield calling code from the &#8220;complexities&#8221; of JDBC.</p>
<pre>// It's important that these references are /outside/ the try/catch
// and that they are set to null. The compiler will enforce this; I'm
// just being explicit.
Connection conn = null;
PreparedStatement ps = null; // I prefer PreparedStatements; use Statement if you want
ResultSet rs = null;

try
{
    conn = ...; // Get your connection however you want

    // Issue your queries and get your results.
    // Remember: if you want to issue multiple queries and/or
    // work with multiple result sets, either declare more Statement
    // and ResultSet locals above and duplicate all cleanup logic for them,
    // or make sure you close each object along the way before you
    // try to re-use the reference.

}
catch (SQLException sqle)
{
    // NEVER swallow exceptions. At least log them using "sql.printStackTrace()"

    // Note that the root exception is being passed-along to the
    // application-specific exception. This allows error messages to include
    // the /full/ stack trace.
    throw new ApplicationException("Error in database code", sqle);
}
finally
{
    // Anyone who has done any real work in Java will know that a 'finally'
    // block will be run after the 'try' block regardless of any exception
    // activity.

    // A couple of things to note, here:
    //   1. Close objects in the proper order: result, then statement,
    //      then connection.
    //   2. Each close gets its own try/catch block. You don't want
    //      the connection to be leaked just because the result set
    //      failed to close properly.
    //   3. Don't throw any exceptions in a finally block. If there is
    //      already an exception "in the air", you'll shoot it down
    //      and replace it with a new one. The original exception is
    //      almost certainly more useful.
    //   4. NEVER swallow an exception. At least log the error.
    //   5. This cleanup code has whitespace removed for brevity.
    //   6. This cleanup code lends itself to being put into a separate
    //      method. I usually have a 'close' method that takes 3 arguments:
    //      Connection, Statement, ResultSet and does the same thing.

    if(null != rs) try { rs.close(); } catch (SQLException sqle)
        {  sqle.printStackTrace(); }
    if(null != ps) try { ps.close(); } catch (SQLException sqle)
        {  sqle.printStackTrace(); }
    if(null != conn) try { conn.close(); } catch (SQLException sqle)
        {  sqle.printStackTrace(); }
}</pre>
<p>That&#8217;s it. Not really that hard, but if you don&#8217;t have your try/catch block straight and the proper code in the finally block, they you are asking to leak connections or other stuff. Java might protect you from a lot of things by collecting its own garbage, but you can still bring down your database server by opening way too many connections and then leaking them all.</p>
<p>Transactions bring another problem to the table because you have to do a rollback unless you want the transaction to commit. Most connection pools default to &#8220;auto-commit&#8221; mode, and the JDBC spec states that calling setAutoCommit(true) commits a transaction if one was in progress. That means that you need to <em>ensure</em> that your transaction is rolled-back&#8230; otherwise it will be committed for you, and that&#8217;s probably not what you want.</p>
<pre>Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;

try
{
    conn = ...; // Get your connection however you want
    conn.setAutoCommit(false); // BEGIN

    // Issue your queries and get your results.

    conn.commit();             // COMMIT
}
catch (SQLException sqle)
{
    // DO NOT allow the call to rollback to throw an exception. See the
    // notes in the 'finally' block in the last example. You could even
    // create your own 'rollback' method to simply do this to clean-up
    // your code a bit.
    if(null != conn) try { conn.rollback(); } catch (SQLException sqle1)
        { sqle1.printStackTrace(); }

    throw new ApplicationException("Error in database code", sqle);
}
catch (ApplicationException ae)
{
    // Yes, catch ApplicationException. Anything that the current method can
    // throw /must/ be caught and re-thrown.

    if(null != conn) try { conn.rollback(); } catch (SQLException sqle)
        { sqle.printStackTrace(); }

    throw ae; // Re-throw the same exception
}
catch (RuntimeException rte)
{
    // You wouldn't want a NullPointerException to end up committing your
    // partial transaction, would you?

    if(null != conn) try { conn.rollback(); } catch (SQLException sqle)
        { sqle.printStackTrace(); }

    throw rte; // Re-throw the same exception
}
catch (Error e)
{
    // Errors, too!

    if(null != conn) try { conn.rollback(); } catch (SQLException sqle)
        { sqle.printStackTrace(); }

    throw e; // Re-throw the same error
}
finally
{
    // Here, I'm taking my own advice to put the cleanup code into a
    // separate method. See how nice this looks?
    this.close(conn, ps, rs);
}</pre>
<p>Following the code samples above will keep your DBAs very happy, and you&#8217;ll never have post a message to a mailing list and have to admit that you really didn&#8217;t know what you were doing when it comes to JDBC programming.</p>
<p>I have a few more general tips for JDBC, connection pools, etc.:</p>
<ol>
<li>In development, set your connection pool to a <em>fixed</em> size of 1 connection. This will let you know immediately if you have any deadlock potential in your code when trying to request more than one connection at a time from the pool. If you <em>do</em> request more than one connection at a time, then there is a possibility that you could deadlock your application waiting on database connections. Just do it. It won&#8217;t hurt, and you might be surprised to find out that you forgot to &#8216;close&#8217; a connection (and therefore return it to the pool). Using this technique will find the error <em>much</em> faster than others.</li>
<li>Use a &#8220;validation query&#8221;. When you request a connection from the pool, you can have the pool validate that the connection is still valid (i.e. connected, etc.) by issuing a simple query to the database. <em>Make this a simple query</em>. Queries like &#8220;SELECT * FROM purchase&#8221; are bad ideas. Choose something like &#8220;SELECT 1 FROM DUAL&#8221; (for you Oracle folks) or &#8220;SELECT 1&#8243; for databases that don&#8217;t require a table name for trivial SELECT queries. If you&#8217;re using MySQL, use &#8220;/* ping */ SELECT 1&#8243; since recent versions of Connector/J can detect the &#8220;/* ping */&#8221; part of the query and issue a super-cheap connection test that doesn&#8217;t even involve the query parser. Why issue a trivial query when you don&#8217;t have to?</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.christopherschultz.net/index.php/2009/03/16/properly-handling-pooled-jdbc-connections/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Indenting HTML &lt;select&gt; options</title>
		<link>http://blog.christopherschultz.net/index.php/2009/02/10/indenting-html-select-options/</link>
		<comments>http://blog.christopherschultz.net/index.php/2009/02/10/indenting-html-select-options/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 19:55:26 +0000</pubDate>
		<dc:creator>Christopher</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.christopherschultz.net/?p=53</guid>
		<description><![CDATA[In CHADIS, we had a requirement to indent certain &#60;option&#62; elements within a &#60;select&#62; dropdown list. Until recently, only team administrators had to use these pages, so we just made it work in Mozilla Firefox and left the other browsers out in the cold. Now that we have some new features that need this capability, [...]]]></description>
			<content:encoded><![CDATA[<p>In <a title="CHADIS" href="http://www.chadis.com/">CHADIS</a>, we had a requirement to indent certain &lt;option&gt; elements within a &lt;select&gt; dropdown list. Until recently, only team administrators had to use these pages, so we just made it work in <a href="http://www.mozilla.com/">Mozilla Firefox</a> and left the other browsers out in the cold. Now that we have some new features that need this capability, I decided to write-up a quick page to demonstrate each technique we tried and how each browser renders them. You can see the investigation and results below. Enjoy.</p>
<p><span id="more-53"></span></p>
<p><strong>Update (2009-06-29): </strong> Andreas Stieger points out that &lt;optgroup&gt; is an possibility, here. Unfortunately, for our purposes, we needed multiple levels of indentation <em>and</em> the options must be selectable. &lt;optgroup&gt;, while easy to implement and relatively consistent rendering across browsers, fails to meet these criteria.</p>
<p>This first dropdown uses only <a title="Cascading Style Sheets" href="http://en.wikipedia.org/wiki/Css">CSS</a> to attempt to indent the select       options. Also, CSS bold property is being used to style the top-level       items while italics are used to style the second-level items.       This ideal rendering was produced by Mozilla Firefox 3.0.6 with no       alterations.</p>
<div id="attachment_57" class="wp-caption alignnone" style="width: 170px"><a href="/wp-content/uploads/2009/02/dropdown_css_styles.png"><img class="size-medium wp-image-57" title="Select dropdown using CSS styles" src="/wp-content/uploads/2009/02/dropdown_css_styles.png" alt="Select dropdown using CSS styles" width="160" height="150" /></a><p class="wp-caption-text">Select dropdown indentation using CSS styles</p></div>
<p>This is how your browser renders the HTML for this technique. View the source to see exactly how it&#8217;s done.</p>
<select id="css_only">
<option style="font-weight:bold;">Top-level item</option>
<option style="padding-left:1em;">First-level item</option>
<option style="padding-left:1em;">First-level item</option>
<option style="padding-left:2em; font-style:italic;">Second-level item</option>
<option style="font-weight:bold;">Top-level item</option>
<option style="padding-left:1em;">First-level item</option>
<option style="padding-left:1em;">First-level item</option>
<option style="padding-left:2em; font-style:italic;">Second-level item</option>
</select>
<p>This next dropdown uses nonbreaking space (&amp;nbsp;) characters to       indent the sub-items. The bold and italic items from the previous       attempt are being left in place. Three &amp;nbsp; characters for each       level of indentation seem to look the best on most browsers.       This ideal rendering was produced by Mozilla Firefox 3.0.6 with no       alterations.</p>
<div id="attachment_58" class="wp-caption alignnone" style="width: 164px"><a href="/wp-content/uploads/2009/02/dropdown_nbsp.png"><img class="size-medium wp-image-58" title="Select dropdown indentation using  " src="/wp-content/uploads/2009/02/dropdown_nbsp.png" alt="Select dropdown indentation using  " width="154" height="150" /></a><p class="wp-caption-text">Select dropdown indentation using  &amp;nbsp;</p></div>
<p>This is how your browser renders the HTML for this technique. View the source to see exactly how it&#8217;s done.</p>
<select id="nonbreaking_spaces">
<option style="font-weight:bold;">Top-level item</option>
<option> First-level item</option>
<option> First-level item</option>
<option style="font-style:italic;"> Second-level item</option>
<option style="font-weight:bold;">Top-level item</option>
<option> First-level item</option>
<option> First-level item</option>
<option style="font-style:italic;"> Second-level item</option>
</select>
<p>Now, em dashes (&amp;mdash;) are used for indentation instead of       nonbreaking spaces, along with a trailing standard space.       Bold and italics are still in place.       This ideal rendering was produced by Mozilla Firefox 3.0.6 with no       alterations.</p>
<div id="attachment_60" class="wp-caption alignnone" style="width: 167px"><a href="/wp-content/uploads/2009/02/dropdown_mdashes.png"><img class="size-medium wp-image-60" title="Select dropdown indentation with &amp;mdash;es" src="/wp-content/uploads/2009/02/dropdown_mdashes.png" alt="Select dropdown indentation with &amp;mdash;es" width="157" height="150" /></a><p class="wp-caption-text">Select dropdown indentation with &amp;mdash;es</p></div>
<p>This is how your browser renders the HTML for this technique. View the source to see exactly how it&#8217;s done.</p>
<select id="emdashes">
<option style="font-weight:bold;">Top-level item</option>
<option>— First-level item</option>
<option>— First-level item</option>
<option style="font-style:italic;">—— Second-level item</option>
<option style="font-weight:bold;">Top-level item</option>
<option>— First-level item</option>
<option>— First-level item</option>
<option style="font-style:italic;">—— Second-level item</option>
</select>
<p>Now, the em dashes (&amp;mdash;) used for indentation are being 	    styled as white-on-white, so they should disappear. 	    Bold and italics are done using &lt;i&gt; and &lt;b&gt; tags.       This ideal rendering was produced by rendering the previous       strategy in Mozilla Firefox 3.0.6 and removing the dashes by hand.</p>
<div id="attachment_61" class="wp-caption alignnone" style="width: 167px"><a href="/wp-content/uploads/2009/02/dropdown_whitened_mdashes.png"><img class="size-medium wp-image-61" title="Select dropdown indentation using whitened &amp;mdash;es" src="/wp-content/uploads/2009/02/dropdown_whitened_mdashes.png" alt="Select dropdown indentation using whitened &amp;mdash;es" width="157" height="150" /></a><p class="wp-caption-text">Select dropdown indentation using whitened &amp;mdash;es</p></div>
<p>This is how your browser renders the HTML for this technique. View the source to see exactly how it&#8217;s done.</p>
<select id="invisible_emdashes">
<option>Top-level item</option>
<option>— First-level item</option>
<option>— First-level item</option>
<option>—— Second-level item</option>
<option>Top-level item</option>
<option>— First-level item</option>
<option>— First-level item</option>
<option style="font-style:italic;">—— Second-level item</option>
</select>
<p>After trying these techniques on the major web browsers, here&#8217;s what I found:</p>
<table style="border:1px solid black; border-collapse:collapse; font-size:small;" border="0">
<tbody>
<tr>
<th style="border:1px solid black;">Browser</th>
<th style="border:1px solid black;">CSS</th>
<th style="border:1px solid black;">nbsp</th>
<th style="border:1px solid black;">mdash</th>
<th style="border:1px solid black;">white mdash (&lt;style&gt;)</th>
<th style="border:1px solid black;">CSS bold/italic</th>
<th style="border:1px solid black;">&lt;b&gt;/&lt;i&gt;</th>
</tr>
<tr>
<td>Microsoft Internet Explorer</td>
<td>no</td>
<td>yes</td>
<td>yes</td>
<td>no</td>
<td>no</td>
<td>no</td>
</tr>
<tr>
<td>Mozilla Firefox</td>
<td>yes</td>
<td>yes</td>
<td>yes</td>
<td>no</td>
<td>yes</td>
<td>no</td>
</tr>
<tr>
<td>Opera</td>
<td>no</td>
<td>yes</td>
<td>yes</td>
<td>no</td>
<td>no</td>
<td>no</td>
</tr>
<tr>
<td>Apple Safari</td>
<td>no</td>
<td>yes</td>
<td>yes</td>
<td>no</td>
<td>no</td>
<td>no</td>
</tr>
<tr>
<td>Google Chrome</td>
<td>no</td>
<td>yes</td>
<td>yes</td>
<td>no</td>
<td>yes</td>
<td>no</td>
</tr>
<tr>
<td>Konqueror</td>
<td>no</td>
<td></td>
<td>no</td>
<td>no</td>
<td>no</td>
<td>no</td>
</tr>
</tbody>
</table>
<p>Looks like using &amp;amp;nbsp; is the best solution for all browsers, and using CSS styling will enhance the display for certain browsers but not interfere with others.</p>
<p><strong>Updated 2009-02-13:</strong> Added Konqueror info.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.christopherschultz.net/index.php/2009/02/10/indenting-html-select-options/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Disabling Password-less SSH Connections</title>
		<link>http://blog.christopherschultz.net/index.php/2008/06/10/disabling-password-less-ssh-connections/</link>
		<comments>http://blog.christopherschultz.net/index.php/2008/06/10/disabling-password-less-ssh-connections/#comments</comments>
		<pubDate>Tue, 10 Jun 2008 13:57:55 +0000</pubDate>
		<dc:creator>Christopher</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[agent]]></category>
		<category><![CDATA[gnome]]></category>
		<category><![CDATA[keyring]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://blog.christopherschultz.net/?p=52</guid>
		<description><![CDATA[I use Ubuntu on a server I use for software development over a VNC session. This is how I learned to do Java software development way back in 2000 at one of my first jobs, and the habit stuck. I recently upgraded to Ubuntu 8.04 LTS (via a completely straightforward and painless upgrade process, I [...]]]></description>
			<content:encoded><![CDATA[<p>I use <a href="http://www.ubuntu.com/">Ubuntu</a> on a server I use for software development over a <a href="http://en.wikipedia.org/wiki/Vnc">VNC</a> session. This is how I learned to do Java software development way back in 2000 at one of my first jobs, and the habit stuck. I recently upgraded to Ubuntu 8.04 LTS (via a completely straightforward and painless upgrade process, I might add) and noticed that something strange was happening: after entering my ssh key password once in a session, I was not asked for it again. <em>Ever</em>.</p>
<p>I leave myself logged into this machine for months at a time, and I never lock it. The only locking you might consider is that I disconnect from the VNC session and re-connecting requires a password. However, I have access to some sensitive information for my job and I&#8217;m a little leery when I&#8217;m allowed access to things unchallenged.</p>
<p>First, I thought something really fishy was going on, until I started reading man pages and doing a little digging. I found out about ssh-agent (which I had previously never heard of, since I&#8217;m usually using command-line-only interfaces) which did not appear to be running. Oddly enough, using ssh-add to flush all cached keys <em>did</em> work, so I was certain that the ssh-agent was lurking somewhere &#8212; I just hadn&#8217;t found it, yet.</p>
<p>Finally, today, I got fed up and apparently entered the magic phrase into Google. The reason I couldn&#8217;t see it running is because the process is gnome-keyring-daemon, not ssh-agent or *agent* or even *ssh*, which makes it tough to find if you don&#8217;t know that it&#8217;s a gnome component that is performing this service. I found the answer in the <a href="http://live.gnome.org/GnomeKeyring/Ssh">Gnome Keyring SSH Agent</a> page on the <a href="http://live.gnome.org/">Gnome Live</a> website. Instructions for disabling ssh key caching are on the page <a href="http://live.gnome.org/GnomeKeyring/Ssh#head-cc8120d1f36ed2ead8e6bd04808494768ae73682">here</a>.</p>
<p>One thing they missed is that you can use gconf-editor to tweak the value indicated in the gconftool-2 instructions. Also, you can change the behavior of a running Gnome system by doing a &#8216;kill -HUP&#8217; on the existing gnome-keyring-daemon process, and then re-starting it with the &#8216;&#8211;components&#8217; that you want (i.e. removing the &#8216;ssh&#8217; service).</p>
<p>Now, I get to enter my password every time I make an ssh connection, just as it should be ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.christopherschultz.net/index.php/2008/06/10/disabling-password-less-ssh-connections/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Finding a decent laptop</title>
		<link>http://blog.christopherschultz.net/index.php/2007/09/21/finding-a-decent-laptop/</link>
		<comments>http://blog.christopherschultz.net/index.php/2007/09/21/finding-a-decent-laptop/#comments</comments>
		<pubDate>Fri, 21 Sep 2007 21:30:05 +0000</pubDate>
		<dc:creator>Christopher</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.christopherschultz.net/?p=50</guid>
		<description><![CDATA[I&#8217;m tech geek, but I&#8217;m a cheap one. I&#8217;m willing to pay or quality, but I also am not one of those people who waits overnight in front of stores to get the latest Shiny Thingâ„¢ so I can show all my friends how cool I am. I casually look for things all the time, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m tech geek, but I&#8217;m a cheap one. I&#8217;m willing to pay or quality, but I also am not one of those people who waits overnight in front of stores to get the latest Shiny Thingâ„¢ so I can show all my friends how cool I am. I casually look for things all the time, and get excited by them, but I rarely<br />
actually buy.</p>
<p>Witness the (somewhat) recent release of the Apple iPhone, over which I have lusted since I first read reliable descriptions back in January. As the release date got closer and closer, the inadequacies of the platform became more and more pronounced (crappy EDGE network, only AT&amp;T plans, can&#8217;t use your own SIM card, can&#8217;t install your own software, <em>phone costs $600</em>, etc.) and Apple failed to get me as a customer. Fortunately for me, I didn&#8217;t pay the $200 &#8220;aren&#8217;t I cool?&#8221; tax like a lot of folks did. Oh, well. At least those folks helped Apple beta-test their platform.</p>
<p>Recently, it&#8217;s become more and more clear that I need a replacement for my computer(s). My recent canine acquisition has effectively moved my home office from our actual office to my couch, since it offers superior surveillance capabilities. I had always worked nearly exclusively on my desktop computer, a great AMD Athlon XP workhorse that has been reliable and stood by me lo these many years since I bought it for my wife so she could play Diablo II with my brother-in-law and me (at which point I decided to take the new computer for myself because hey, what does my wife need with all that processing power?). When I was out and about, I used my somewhat less-trusty 17-inch HP <strike>electric blanket</strike> notebook, but it never really felt right, since I&#8217;ve always been a desktop kinda guy. Using the laptop more and more (on the couch) has made it clear that both computers need to go: I need a laptop, and this one is falling apart; if I need a laptop, why do I need a desktop at all &#8212; as long as I can have a nice, big screen to plug into when I&#8217;m actually at my desk.</p>
<p>Thus begins my quest to find a suitable laptop to take over all my computing needs.</p>
<p>Don&#8217;t forget: I said I was willing to pay for quality, but I also said I was cheap. I also didn&#8217;t say it, but I&#8217;m not going to lug around 10 pounds of laptop anymore. No, sir.</p>
<p>My actual needs are few: anything that can outperform my existing 3 GHz hyper-threaded processor without setting my legs on fire is adequate. I also need lots of RAM since I like to run a thousand things at once. The games that I do actually play are old in terms of graphics requirements, so I don&#8217;t exactly need a top-of-the-line gaming platform.</p>
<p>Given my requirements, why is it so hard to find a decent laptop these days? Apparently, my requirements are more strict than I had first let on. What I really want is:</p>
<ul>
<li>800-MHz FSB with <em>matching-speed</em> memory</li>
<li>A high-resolution screen (WSXGA+ would be preferred)</li>
<li>Discrete graphics memory on a good mobile graphics board</li>
<li>Gigabit Ethernet</li>
<li>Digital video output</li>
<li>Low weight</li>
<li>Reasonable price (less than $1500 including 1-yr warranty)</li>
</ul>
<p>Actually, I&#8217;m willing to sacrifice a little weight to meet the other criteria. Ideally, I&#8217;d like to make it under 7 pounds including the power brick, but that appears to be difficult to accomplish in the 15-inch screen size.</p>
<p>So, what are the problems?</p>
<ul>
<li>Many companies will allow you to select the new 800MHz  FSB processors, but they won&#8217;t give you matching-speed memory. So much for a faster FSB.</li>
<li>I have been able to find WSXGA+ on only a few laptops. I realize this is pretty expensive, so most vendors don&#8217;t even give you the option. I can give this up if necessary, especially since I&#8217;ll mostly be using higher-resolutions on my external monitor, anyway.</li>
<li>Mobile graphics cards just suck in comparison to their desktop-based brethren: it&#8217;s a fact. It still shouldn&#8217;t stop me from getting something nice in the graphics department. Every single laptop in these price ranges should have the option of discrete graphics memory (with reasonable on-board memory sizes: 128MB is not enough these days, guys!).</li>
<li>Virtually nobody has gigabit Ethernet. Why? I can&#8217;t even imagine. You can get a desktop gigabit card for five bucks. I should be able to get a mobile one for fifty. It&#8217;s sad that the wired options for laptops are faster than the wired ones these days.</li>
<li>Many companies (Dell, I&#8217;m looking at <em>you</em>) don&#8217;t support HDMI or even DVI video output yet. Why? Especially Dell: they sell these big, fat displays that all have DVI and HDMI inputs on them, and their laptops need special adapters to utilize the superior-quality digital signals.</li>
<li>Weight is always a problem: sturdy construction plus lots of components equals many pounds. I get it. Why can I get the same components in 3 different systems and have the weights all be wildly different? Sigh.</li>
</ul>
<p>I can get various combinations of the above on different units from different manufacturers (except gigabit Ethernet), but I can&#8217;t find the one unit that has all of them. It&#8217;s always a trade-off: do I want proper speed-matched memory and CPU or do I want a decent graphics card? Do I want a slick hi-def screen or do I want HDMI output? It&#8217;s maddening.</p>
<p>I have given up the laptop search for this month. Maybe around Thanksgiving, when hardware manufacturers completely lose their minds just so they can move inventory regardless of the cost, I&#8217;ll be able to get something whose flaws I don&#8217;t mind accepting because I&#8217;m getting such an insane deal on the price.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.christopherschultz.net/index.php/2007/09/21/finding-a-decent-laptop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Interesting new WWW attack vector</title>
		<link>http://blog.christopherschultz.net/index.php/2007/02/23/interesting-new-www-attack-vector/</link>
		<comments>http://blog.christopherschultz.net/index.php/2007/02/23/interesting-new-www-attack-vector/#comments</comments>
		<pubDate>Fri, 23 Feb 2007 23:28:15 +0000</pubDate>
		<dc:creator>Christopher</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.christopherschultz.net/?p=46</guid>
		<description><![CDATA[While I suppose that using javascript for evil purposes isn&#8217;t exactly a new idea, Bruce Schneier has written a piece (also covered on Slashdot and, I&#8217;m sure, other places) about three guys who have developed an attack that royally screw most users&#8217; ability to use their Internet connection again. AJAX, the magic pixie dust used [...]]]></description>
			<content:encoded><![CDATA[<p>While I suppose that using javascript for evil purposes isn&#8217;t exactly a new idea, Bruce Schneier has written a <a href="http://www.schneier.com/blog/archives/2007/02/driveby_pharmin.html">piece</a> (also covered on <a href="http://it.slashdot.org/article.pl?sid=07/02/16/1421238">Slashdot</a> and, I&#8217;m sure, other places) about three guys who have developed an attack that royally screw most users&#8217; ability to use their Internet connection again.</p>
<p>AJAX, the magic pixie dust used heavily on sites like Google Mail, is really just javascript with the ability to make HTTP requests and parse the results of those requests. Javascript has been available in browsers for years and is recently enjoying some interest by web developers because of that last (somewhat) new capability. The use of this technology for evil is nearly indistinguishable from legitimate use, so it&#8217;s hard for any software to detect it and prevent it.</p>
<p>Basically, the attacker sets up a web site with some javascript code (see below) and tricks you into visiting that site. It&#8217;s not all that hard to get people to look at a rogue site: you can either spam the entire world and expect that a certain percentage of email readers are suckers who will click on the links in those messages, or you can hack a major site (such as <a href="http://blogs.zdnet.com/security/?p=15&amp;tag=nl.e589">Dolphin Stadium</a>) and insert the exploit into it.</p>
<p>Now, the fun begins. This piece of javascript code (which, as I mentioned earlier, is pretty much impossible to identify as evil) attempts to make a connection to <em>your router</em>. If you are like most home users, your router is still sitting there with it&#8217;s default, factory-set password (probably something stupid like &#8220;admin&#8221;). That means that this piece of javascript code can login to your router and start playing around. This particular attack is designed to change your DNS settings such that all requests for named Internet addresses go to malicious servers. Those requests will be answered with fraudulent IP addresses which can be used to either emulate your favorite website or simply serve nothing but pop-up ads and porn. This little hack could even change your router&#8217;s password, locking you out of your own hardware.</p>
<p>Imagine if you were to fall victim to this exploit&#8230; the next time you tried to access, say, www.bankofamerica.com, the rogue DNS server sends you to what really is www.evilbankofamerica.com. The site looks like Bank of America&#8217;s real site, and you fall for the bait. You enter your username and password for online banking, and bang! &#8211; the bad guys have your online banking credentials.</p>
<p>SSL certificates might save you, since VeriSign (and others) are unlikely to issue an SSL cert for &#8220;www.bankofamerica.com&#8221; to an entity that is not Bank of America. But what do you think most people do when they get a security warning these days? My guess is that most people do whatever they have to do in order to get the security warning to go away and let them look at their website. That is a recipe for disaster.</p>
<p>Since we&#8217;re talking about folks who have never changed their router&#8217;s password, they probably wouldn&#8217;t know how to recover from this problem, either. If the attack included changing your router&#8217;s password, you&#8217;ll have to reset it to factory defaults in order to get back up and running again.</p>
<p>I&#8217;m guessing most home users will ask friends what to do if every site they visit is just porn and popups. The advice they are going to get is to reinstall their operating system (statistically it will be Microsoft Windows, which has a bad reputation for becoming easily infested). Many users aren&#8217;t willing to do that, and will pay someone else to do it. Re-installing the OS won&#8217;t work, so those users are likely to do the next best thing: go out and buy a new computer. That won&#8217;t work either.</p>
<p>What a pain in the ass.</p>
<p>What a great exploit.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.christopherschultz.net/index.php/2007/02/23/interesting-new-www-attack-vector/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Blog moved to virtual host</title>
		<link>http://blog.christopherschultz.net/index.php/2007/02/13/blog-moved-to-virtual-host/</link>
		<comments>http://blog.christopherschultz.net/index.php/2007/02/13/blog-moved-to-virtual-host/#comments</comments>
		<pubDate>Tue, 13 Feb 2007 20:32:48 +0000</pubDate>
		<dc:creator>Christopher</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.christopherschultz.net/?p=45</guid>
		<description><![CDATA[The whine of my rack server has finally gotten to me. So, in spite of the home heating advantages, after more than 2 years of hosting my own website, blog, and mail server in my home, it&#8217;s time to get it out of here. I found a relatively low-cost virtual hosting plan where I have [...]]]></description>
			<content:encoded><![CDATA[<p>The whine of my <a href="/?p=17" title="Nice Rack">rack server</a> has finally gotten to me.</p>
<p>So, in spite of the home heating advantages, after more than 2 years of hosting my own website, blog, and mail server in my home, it&#8217;s time to get it out of here.</p>
<p>I found a relatively low-cost virtual hosting plan where I have free reign of my own virtual machine. Sadly, I couldn&#8217;t use <a href="http://www.gentoo.org/" title="Gentoo Linux">Gentoo</a> &#8211; my preferred Linux distribution &#8211; so I had to settle for <a href="http://www.debian.org/" title="Debian Linux">Debian</a>, whose package manager is absolutely maddening to me.</p>
<p>At any rate, we&#8217;ll see how things go. So far, the MySQL upgrade (Debian&#8217;s latest stable version of 4.0? WTF?) and WordPress installation (no stable version available through Debian?!) have been relatively painless. Let&#8217;s just hope that everything else goes well.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.christopherschultz.net/index.php/2007/02/13/blog-moved-to-virtual-host/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Attempting AJAX</title>
		<link>http://blog.christopherschultz.net/index.php/2006/10/23/attempting-ajax/</link>
		<comments>http://blog.christopherschultz.net/index.php/2006/10/23/attempting-ajax/#comments</comments>
		<pubDate>Mon, 23 Oct 2006 16:16:02 +0000</pubDate>
		<dc:creator>Christopher</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://blog.christopherschultz.net/?p=42</guid>
		<description><![CDATA[So, AJAX is one of the more recent causes of excitement in the web-based application delivery world. The first major site to feature AJAX (as far as I know) was Google&#8217;s gmail. Assuming that you are okay with writing tons of Javascript, it&#8217;s quite a nice way to spice up your application enough to make [...]]]></description>
			<content:encoded><![CDATA[<p>So, AJAX is one of the more recent causes of excitement in the web-based application delivery world. The first major site to feature AJAX (as far as I know) was Google&#8217;s gmail. Assuming that you are okay with writing tons of Javascript, it&#8217;s quite a nice way to spice up your application enough to make your users feel a little less like they&#8217;re using a web-based app.</p>
<p>I have to admit that I generally like to use the minimum of Javascript on my sites that can possibly work, because it usually doesn&#8217;t. Javascript is notorious for failing on various browsers and platforms with no specific rhyme or reason. Most often, it is because the application developer did not take the time to test and debug the Javascript on various browsers, or failed to use standards-compliant code and chose a single target browser (this more often happens when an application is targeted towards Microsoft Internet Explorer).</p>
<p>My rule of thumb is that Javascript should not be used unless there is some non-Javascript backup for the same functionality. Basically, Javascript may only be used to <em>enhance</em> the user interface; it cannot be used to <em>drive</em> the user interface.</p>
<p>We have a page that allows users to tick items off of a list. The list is pagenated, to it can be quite long. They can either tick them or un-tick them, and the page reflects the current status of each item. There is one big problem with this type of interface: the user expects to interact with a standard widget (the checkbox), but the page itself does not respond to checking or unchecking the checkbox: you have to submit a form. This basically won&#8217;t work because users are not going to tolerate having to check these items and then click a button, especially when moving from one page to another. They might also tick an item and then leave the page entirely. There is no way to stop them, and the only way to capture the event of ticking the checkbox is to use Javascript.</p>
<p>I am unhappy with the Javascript-only solution because it breaks down when the user&#8217;s browser does not have Javascript available. The user might not have Javascript available because of the browser (think lynx), or because they have turned off Javascript for security reasons, or because their Javascript implementation is buggy and isn&#8217;t going to work for some reason. Another approach is required.</p>
<p>My solution in the past was to make the checkbox into an image that looks like a checkbox, but it actually a link. That link points to the URL that selects (or de-selects) the item in question, which then re-displays the page with the proper status update. This works very well, except for the fact that the page view often re-sets itself back to the top of the page. That is inconvenient when you want to select multiple items from the same page, and you have to scroll down the page to see them.</p>
<p>This is a perfect example of when I have a non-Javascript solution working that could be significantly improved through the use of Javascript.</p>
<p>Enter AJAX.</p>
<p>If all the planets are aligned (i.e. the user has Javascript available and enabled, and it supports AJAX, and nothing else goes wrong), we can use some AJAX magic to improve the user experience.</p>
<p>AJAX is little more than a single (at least, from an AJAX developer&#8217;s point of view) very useful Javascript object called XMLHttpRequest. It&#8217;s job is to make an asynchronous HTTP request to some URL and provide the response either as text or as an XML document. If you elect to use the response as an XML document, then you can use the standard DOM methods to traverse everything.</p>
<p>I started out by consulting Mozilla&#8217;s <a href="http://developer.mozilla.org/en/docs/AJAX:Getting_Started">AJAX:Getting Started</a> page. It gives a fairly straightforward example of, well, getting started with AJAX. Using the information presented on that page, I was able to get something up and working relatively quickly. They had even listed the changes I would have to make in order to use the code under Microsoft Internet Explorer, so I figured I was covered when I went to test on MSIE.</p>
<p>Unfortunately, there&#8217;s a relatively large caveat when using MSIE up through version 6 when working with XML: the document.getElementsByTagName function is not namespace-aware. That means that those of us who came out from under the non-namespace-using rock several <em>years</em> ago have to deal with some pretty stupid code in order to work around it.</p>
<p>At this point, AJAX pros are saying to themselves &#8220;why doesn&#8217;t this guy just use one of the dozen or so cross-platform AJAX libraries that are out there &#8212; then he won&#8217;t have this problem&#8221;. Well, I&#8217;ll tell you: because I wanted to solve the problem myself in order to understand what was going wrong. It did take quite a while, and I ended up using information presented on Apple&#8217;s Dynamic HTML and XML: <a href="http://developer.apple.com/internet/webcontent/xmlhttpreq.html">The XMLHttpRequest object</a>. This was the only place where I saw any mention of MSIE&#8217;s failure to support namespaces.</p>
<p>Working around non-namespace-aware Javascript is pretty ugly. Under normal circumstances, one would simply call document.getElementsByTagName and pass the &#8220;local name&#8221; of the element to that function. You&#8217;d get an array of nodes back and everything would be fine. But, since MSIE sees &#8220;foo:bar&#8221; as the local name (instead of just &#8220;bar&#8221;), you&#8217;d have to change your code to look for &#8220;foo:bar&#8221;. But, that wouldn&#8217;t work in browsers that are namespace-aware, and it&#8217;s difficult, if not impossible, to tell at runtime which way a browser will behave.</p>
<p>So, I was forced to implement my own function that loops through the children of a particular node and looks for matching elements. :(</p>
<p>It occured to me just now that I could probably get away with making two calls: one that uses the preferred method, and then, if the call returns no nodes, another that calls the same method with the namespace attached. The only problem with this option is that you have to know the text of the namespace that is being used. Typically, you only have to deal with the namespace URI instead of the actual value being used (such as &#8220;foo&#8221; in the example above). In this case, I&#8217;ll have to hard-code the namespace into the Javascript, which is non-ideal. My existing solution has no such restrictions, so I&#8217;ll probably keep it for the time being.</p>
<p>A special thanks to the MSIE team for once again stepping outside of the standard (which, in all fairness, may or may not have existed at the time of implementation) and spicing up my day.</p>
<p>Now, time to test on MSIE 7. And Opera. And Safari&#8230;.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.christopherschultz.net/index.php/2006/10/23/attempting-ajax/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>(Yet Another) Microsoft Internet Explorer Rendering Bug</title>
		<link>http://blog.christopherschultz.net/index.php/2006/03/21/yet-another-microsoft-internet-explorer-rendering-bug/</link>
		<comments>http://blog.christopherschultz.net/index.php/2006/03/21/yet-another-microsoft-internet-explorer-rendering-bug/#comments</comments>
		<pubDate>Tue, 21 Mar 2006 19:49:45 +0000</pubDate>
		<dc:creator>Christopher</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.christopherschultz.net/?p=39</guid>
		<description><![CDATA[Microsoft Internet Explorer always has the more interesting interpretations of markup.]]></description>
			<content:encoded><![CDATA[<p>For years, standard operating procedure for developing a web application would be to design and implement it with Microsoft&#8217;s Internet Explorer as the test bed. You&#8217;d pick a version and tell everyone that they needed to use it and that was that. I have to admit that even I committed such sins.</p>
<p>These days, I want my pages to be usable on as wide a variety of web browsers as possible, so I use Mozilla Firefox for development, and then just check MSIE at the end to see if anything is amiss. Yet, with MSIE, something is almost always amiss&#8230;</p>
<p>I&#8217;ve had trouble with good-looking logos and mastheads for a long time. Back in the day, tables were the way to go. More recently, CSS is the preferred (and really the only) way to do layouts. The trouble is that MSIE has some schizophrenia when it comes to CSS. The folks that wrote MSIE implement only part of the CSS specifications, and often took shortcuts whenever they wanted.</p>
<p>A few days ago, I noticed that MSIE was acting strangely when viewing one of my current projects. It appeared that the text in my masthead wasn&#8217;t being displayed. Perhaps I had some conflicting CSS styles that were giving my text the same background and foreground colors. I checked, and everything was okay. Reload after reload, application server restart after application server restart didn&#8217;t solve the problem. Mozilla Firefox never blinked an eye and rendered the (quite simple) page without a problem.</p>
<p>Then, I noticed that scrolling the page past the fold and back again would mysteriously reveal the text. That&#8217;s <em>not</em> something that can be done using CSS.</p>
<p>Check out this movie that demonstrates the problem:</p>
<p><a title="Demonstration Movie (3.3MB)" href="/wp-content/uploads/older/ie_rendering_bug/demo.mpg"><img style="border: 1px solid black" alt="Screenshot of MSIE Rendering Bug" src="/wp-content/uploads/older/ie_rendering_bug/screenshot.png" /></a></p>
<p>It&#8217;s definitely a bug. The markup is validated correct strict XHTML 1.0 and the CSS is also spick-and-span clean.</p>
<p>The markup is fairly straightforward; there&#8217;s a <em>div</em> surrounding the entire masthead (both the topmost blue bar and the bar containing the tri-colored regions), and then a <em>div</em>containing everything within the topmost blue bar. The blue bar contains a <em>form</em> containing the login form. All the other text elements are plain-old <em>h1</em> and <em>h2</em> <em>h2</em>elements. The tri-colored regions live in their own <em>div</em>and are made up of the surrounding <em>div</em>(black background) and two nested <em>div</em>elements with appropriate background colors.</p>
<p>The styles are also straightforward; colors, margins, borders, etc. I didn&#8217;t even have to use the &#8216;line-height&#8217; trick to get MSIE to display an empty <em>div</em>(for the tri-colored regions).</p>
<p>It turns out that the problem can be solved by adding a simple non-breaking space between the blue-bar and tri-colored-bar <em>div</em>elements. MSIE interprets this change by finally giving me what I wanted in the first place. Unfortunately, it adds a small vertical space before the tri-colored-bar which I would prefer not to have&#8230; it looks like unnecessary padding in the blue <em>div</em>.</p>
<p>I have a virtual machine running Microsoft Windows XP with MSIE 7 beta running on it, so I decided to comfort myself with the fact that MSIE 7 had probably fixed this bug. It hasn&#8217;t, at least not yet. I hope the MSIE engineers really try to get CSS right this time.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.christopherschultz.net/index.php/2006/03/21/yet-another-microsoft-internet-explorer-rendering-bug/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hyperthreading CPUs and User Experience</title>
		<link>http://blog.christopherschultz.net/index.php/2005/11/29/youre-wrong-okay-maybe-not-but-come-on-and-take-a-look/</link>
		<comments>http://blog.christopherschultz.net/index.php/2005/11/29/youre-wrong-okay-maybe-not-but-come-on-and-take-a-look/#comments</comments>
		<pubDate>Wed, 30 Nov 2005 03:10:01 +0000</pubDate>
		<dc:creator>Christopher</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.christopherschultz.net/?p=36</guid>
		<description><![CDATA[Brian has an article on his blog about Hyperthreaded CPUs and their effects on &#8220;the user experience&#8221;, by which I&#8217;m sure he means the typical response on a graphical desktop to a user&#8217;s actions &#8212; something like moving the mouse, dragging a window, opening-up a menu, etc. I disagree with a few of his assertions&#8230; [...]]]></description>
			<content:encoded><![CDATA[<p>    <a href="http://ardvaark.net/">Brian</a> has an article on his blog about    <a href="http://arstechnica.com/articles/paedia/cpu/hyperthreading.ars">Hyperthreaded</a>    CPUs and their effects on &#8220;the user experience&#8221;, by which I&#8217;m sure he means    the typical response on a graphical desktop to a user&#8217;s actions &#8212; something like    moving the mouse, dragging a window, opening-up a menu, etc.</p>
<p>    I disagree with a few of his assertions&#8230; namely that HT itself is responsible for    improving the user experience. For example, if you have a single (and non-HT)    processor and you run some CPU-intensive process (such as a compiler, a    complex graphical manipulation that doesn&#8217;t take advantage of your graphics    processor, or a poorly written program that runs away with your CPU in a tight    loop), that process is going to eat cycles that would otherwise be used to    redraw your mouse pointer (hardware-drawn cursors went away with Microsoft    Windows 3.1), draw the menus in your spreadsheet program, or drag your    windows around the screen. This makes the responsiveness of your graphical    desktop seem sluggish.</p>
<p>    The reason this happens is that CPUs can only do one thing at a time.    Fortunately, they typically do things <i>reeeeeally</i> fast, so you don&#8217;t notice    that it&#8217;s only doing that one thing at a time because it switches tasks and does a    little bit of work here and a little bit of work there, and it magically looks like    everything is getting done &#8220;all at the same time&#8221;.</p>
<p>    With HT, the CPU itself can <i>actually do more than one thing at a time</i>.    Sure, the CPU still does that frienzied-switcheroo dance, except that it can    &#8212; ostensibly, anyway &#8212; do work on two whole tasks at once. Brian mentions    that HT isn&#8217;t as nice as actually having two equally-fast processors, but let&#8217;s    ignore that fact for the moment.</p>
<p>    I assert that the responsiveness of the graphical desktop has more to do with the    way that the desktop functions than the way the CPU works. Evidence?    Compare any version of Microsoft Windows with a similar machine running    Linux and any one of the graphical desktops that run atop it. When you launch    a program under Microsoft Windows, you get an hourglass mouse pointer,    the computer churns for a while, and the program window eventually opens.    The next time you do that, move the mouse around&#8230; try to open another    application&#8230;. try to drag another window around. For the most part, your    desktop will respond quite favorably. The mouse cursor will smoothly follow    your hand motions, the windows will redraw, and the second application will    also eventually open.</p>
<p>    My experience with Linux is not the same. If I open an application, the mouse    cursor immediately starts jerking around and loses its smoothness. With the    mouse jerking around, the windows jerk around as well. Other apps will start,    of course, but it&#8217;s really still like dropping menus down and moving the mouse    that people really notice.</p>
<p style="margin-left:20%; margin-right:20%; font-style:italic">    Note to Linux zealots: I totally love Linux. I run it on everything except the    computer that I use as my primary desktop, mostly because of games that I    want to play. Yeah, Wine just doesn&#8217;t work for me. Get over it.</p>
<p>    Anyway, these observations lead me to believe that Microsoft Windows, no    doubt through some kind of unholy voodoo, has gone through great pains to    schedule the user interface at the highest possible priority. Linux, in typical    pragmatic style, has chosen not to hijack the CPU for such trivial details as    turning your mouse pointer into the <a href="http://www.energizer.com/images/bunny/bio/bunny.jpg">Energizer Bunny</a>.</p>
<p>    As for Brian&#8217;s compiler running in a virtual machine, it&#8217;s a shame that VMWare    doesn&#8217;t properly expose both processors available to Microsoft Windows to    the OS running in the virtual machine. I would expect that a decent    virtualization environment would allow you to set the number of CPUs to    expose to the guest OS. I would have expected his gentoo compile to    be able to peg <i>both</i> of his virtual CPUs.</p>
<p>    But back to CPU utilization versus user experience. I would bet that if he were    using a threaded compiler (which almost doesn&#8217;t make any sense) directly    in his Microsoft Windows environment, and compiling the same code (or at    least performing a compile that was equally CPU-intensive), then both    HT CPUs would be pegged, and he&#8217;d still be able to move the mouse around,    click on things (with a slight delay), etc.</p>
<p>    I think it comes down to scheduling. Your OS can always interrupt your compiler    for any reason. Your compiler (well, really your VM) is probably scheduled at    in &#8220;normal&#8221; mode, whatever that means for your OS. I&#8217;m willing to bet    dollars-to-doughnuts (mmmm&#8230; doughnuts) that Microsoft Windows&#8217;s graphical    shell itself (explorer?) is scheduled at a higher-than-normal priority,    or that all the UI calls that it makes are either running at the kernel level    (which wouldn&#8217;t suprise me one bit for MS Windows, honestly) or at a    higher-than-normal priority. It&#8217;s not the CPU, it&#8217;s the scheduler.</p>
<p>    There are a lot of folks out there that say that HT is actually hurting    performance. I haven&#8217;t read any of them, &#8217;cause I&#8217;m honestly not that interested    in looking at those numbers. After reading the ARS article linked above    a few years ago, I thought that some really smart dudes got really high one    day and had themselves a fantastic idea. I figured that it wasn&#8217;t as cool as the    hype would suggest, but hey&#8230; why not squeeze as much out of the CPU as you    possibly can? My gut reaction is that you can find data to either support    or deride HT technology. I do know one thing: lots of Java developers were    complaining in the past that HT CPUs would crash all the time with very strange    errors, and turning off HT would solve their problems. &gt;shrug&lt;.    You gotta do what you gotta do. Too bad those folks paid extra for their    super-sexy HT processors.</p>
<p>    I had a friend at <a href="http://www.rose-hulman.edu">Rose-Hulman</a>    that used to play <a href="http://www.unrealtournament.com/">Unreal    Tournament</a> with a couple of friends and me. He had just gotton a    dual-CPU machine and decided to play with it a little: he created a dedicated    server and set the <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDiagnosticsProcessClassProcessorAffinityTopic.asp">processor affinity</a>    to his second processor (i.e. not the primary one). Then, he started UT in    client mode so he could play it, and set the processor affinity for <i>that</i>    process to the primary CPU. I&#8217;m not sure if it really made any difference than    just running them separately with no tweaks, but it was an interesting idea.</p>
<p>    When I heard that he had done that, I decided that since the OS itself actually    needs very little CPU time to do it&#8217;s stuff, that an OS that could monopolize    a considerably lower-powered processor and then schedule all user tasks on    a much higher-powered processor would be great. Super-fast memory allocation    (not that it&#8217;s particularly slow in the first place), buffer management, DMA,    etc. For most OSs, this also means that the various hardware drivers would    run on a CPU that wasn&#8217;t being used for applications. That would speed-up    graphics processing since even a computer with the latest monster GPU    still needs the graphics driver to actually send the data to the GPU to do    the work.</p>
<p>    Who knows. Maybe someone will steal my idea and make a jillion dollars.    That would really suck for me.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.christopherschultz.net/index.php/2005/11/29/youre-wrong-okay-maybe-not-but-come-on-and-take-a-look/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
