<?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>tdistler.com &#187; Linux</title>
	<atom:link href="http://tdistler.com/tag/linux/feed" rel="self" type="application/rss+xml" />
	<link>http://tdistler.com</link>
	<description>&#34;To err is human, but to really foul things up you need a computer.”</description>
	<lastBuildDate>Wed, 16 May 2012 03:00:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Cross-Platform IPv6 Socket Programming</title>
		<link>http://tdistler.com/2011/02/28/cross-platform-ipv6-socket-programming</link>
		<comments>http://tdistler.com/2011/02/28/cross-platform-ipv6-socket-programming#comments</comments>
		<pubDate>Tue, 01 Mar 2011 04:00:39 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[IPv6]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=793</guid>
		<description><![CDATA[Writing code that works on Windows, Linux, and Mac is frequently challenging. Socket programming is no exception. Modern versions of Linux and Mac have full implementations of the latest IPv6 socket API extensions defined in RFC 3493. Windows, however, has only a partial implementation of the original (deprecated) version, RFC 2553. This sounds worse than [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/02/network.jpg"><img class="alignright size-thumbnail wp-image-795" title="network" src="http://tdistler.com/wp-content/uploads/2011/02/network-150x150.jpg" alt="IPv6 Networking" width="150" height="150" /></a>Writing code that works on Windows, Linux, and Mac is frequently challenging. Socket programming is no exception. Modern versions of Linux and Mac have full implementations of the latest IPv6 socket API extensions defined in <a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>. Windows, however, has only a partial implementation of the original (deprecated) version, <a title="IETF RFC 2553" href="http://tools.ietf.org/html/rfc2553" target="_blank">RFC 2553</a>. This sounds worse than it is, but it&#8217;s something you have to consider.</p>
<p><em><strong>Note</strong></em>: This post assumes you are already familiar with the socket extensions for IPv6 (<a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>).</p>
<p><strong>Linux and Mac</strong><br />
Good news&#8230; they both fully support <a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>.</p>
<p><strong>Windows</strong><br />
Windows IPv6 support varies based on which version you&#8217;re targeting. Microsoft started adding IPv6 in Windows 2000, and they&#8217;ve continued adding more of the socket extensions as time went on. Most of the core functionality is present in XP, and what&#8217;s missing is easily replaced by using Winsock calls directly (more on this later).</p>
<p>Windows gained IPv6 support while <a title="IETF RFC 2553" href="http://tools.ietf.org/html/rfc2553" target="_blank">RFC 2553</a> was still the supported standard. Since then, it has been deprecated by <a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>. However, Microsoft doesn&#8217;t want to break existing code written against it&#8217;s API, so the older API lives on. The main impact of this is that <code>sockaddr_in6</code> and <code>sockaddr_storage</code> are slightly different on Windows than Mac and Linux. The size of the structures across platforms is the same (the <code>sa_family_t</code> member was shortened), it&#8217;s just that the Windows structures don&#8217;t begin with the length member. For example:</p>
<pre><code>// Linux and Mac
struct sockaddr_in6 {
    uint8_t      sin6_len;    /* Added in RFC 3493 */
    sa_family_t  sin6_family;
    ...
};
struct sockaddr_storage {
    uint8_t      ss_len;      /* Added in RFC 3493 */
    sa_family_t  ss_family;
    ...
};

// Windows
struct sockaddr_in6 {
    sa_family_t  sin6_family;
    ...
};
struct sockaddr_storage {
    sa_family_t  ss_family;
    ...
};</code></pre>
<p>I&#8217;ve never had a problem with this, because the size of <code>sockaddr_in6</code> is easily determined (<code>sizeof(sockaddr_in6)</code>) and I always end up casting <code>sockaddr_storage</code> to the specific type (<code>sockaddr_in</code> or <code>sockaddr_in6</code>) based on <code>ss_family</code>.</p>
<p>Besides the data structure differences, it&#8217;s important to remember that Microsoft added IPv6 support over multiple versions. Support first appeared in Windows 2000, but more of the extensions have been added over time. Most of the core functionality was present in XP (including multicast), but not everything is implemented as of Windows 7. It&#8217;s annoying, but I will say that what&#8217;s missing is easily replaced by using Winsock calls directly.</p>
<p>Here&#8217;s the breakdown of IPv6 socket extensions by Windows version:</p>
<table border="1" width="570">
<tbody><!-- Results table headers --></p>
<tr>
<th>Socket Extension</th>
<th>2K</th>
<th>XP</th>
<th>Vista</th>
<th>7</th>
<th>Comments</th>
</tr>
<tr>
<td>if_indextoname()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>GetAdaptersAddresses() for XP</td>
</tr>
<tr>
<td>if_nametoindex()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>GetAdaptersAddresses() for XP</td>
</tr>
<tr>
<td>if_nameindex()</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>GetAdaptersAddresses() (XP, later)</td>
</tr>
<tr>
<td>if_freenameindex()</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>getaddrinfo()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>getnameinfo()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>freeaddrinfo()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>gai_strerror()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>inet_pton()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>WSAStringToAddress() (2000, XP)</td>
</tr>
<tr>
<td>inet_ntop()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>WSAAddressToString() (2000, XP)</td>
</tr>
<tr>
<td>All IN6_IS_ADDR_* macros</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>Ex: IN6_IS_ADDR_LOOPBACK()</td>
</tr>
<tr>
<td>struct sockaddr_storage</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>Multicast support</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
</tbody>
</table>
<p>As you can see, you may still have to call Winsock directly depending on what version of Windows you are targeting. In my opinion, programming IPv6 on Windows is a lot easier if you only support XP and later, but I know that&#8217;s not always possible.</p>
<p><strong>Summary</strong></p>
<p>Modern operating systems all support IPv6. However, for business reasons, Windows has a slightly older version of the socket API which requires special consideration. My goal was to enumerate those differences to help make the transition to IPv6 smoother. Writing cross-platform code can be a fun challenge at times, but it&#8217;s also a little tedious. Hopefully, this post helps ease the pain.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/02/28/cross-platform-ipv6-socket-programming/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Audio Resampling Using FFMpeg (avcodec)</title>
		<link>http://tdistler.com/2010/07/22/audio-resampling-using-ffmpeg-avcodec</link>
		<comments>http://tdistler.com/2010/07/22/audio-resampling-using-ffmpeg-avcodec#comments</comments>
		<pubDate>Thu, 22 Jul 2010 19:01:38 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=427</guid>
		<description><![CDATA[FFMpeg provides many powerful features for processing audio and video. One cool thing it can do is resample an audio stream. This allows you to convert, say, a 44.1kHz audio stream down to 8kHz, or up to 48kHz. What&#8217;s more, FFMpeg can do the conversion to any arbitrary sample rate. This allows you to do [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2010/07/ffmpeg_logo.jpg"><img class="alignright size-full wp-image-433" title="ffmpeg_logo" src="http://tdistler.com/wp-content/uploads/2010/07/ffmpeg_logo.jpg" alt="" width="150" height="37" /></a><a title="FFMpeg" href="http://www.ffmpeg.org/" target="_blank">FFMpeg</a> provides many powerful features for processing audio and video. One cool thing it can do is resample an audio stream. This allows you to convert, say, a 44.1kHz audio stream down to 8kHz, or up to 48kHz. What&#8217;s more, FFMpeg can do the conversion to any arbitrary sample rate. This allows you to do cool things like smoothly changing the audio playback speed over time (see sample code below).</p>
<p>There are many pages describing how to resample audio using the ffmpeg command line application, but what about doing resampling in your own program? To do that, you need to use the avcodec library (<code>libavcodec.so</code> on Linux and <code>avcodec.dll</code> on Windows).</p>
<ol>
<li>Include <code>avcodec.h</code></li>
<li>Call <code>avcodec_init()</code> to initialize the FFMpeg library.</li>
<li>Create a resampling context using <code>av_resample_init()</code> that describes how you want the resampling done.</li>
<li>Call <code>av_resample()</code> to do the actual resampling on your audio buffer.</li>
<li>When you&#8217;re done with the resampling context, delete it with <code>av_resample_close()</code>.</li>
<li>Finally, link your application against <code>avcodec</code>, <code>avutil</code>, and <code><a title="zlib Library" href="http://www.zlib.net/" target="_blank">zlib</a></code> (it won&#8217;t work on Linux without this one).</li>
</ol>
<p>Here it is in pseudocode:</p>
<blockquote><p><code>#include "libavcodec/avcodec.h"</code></p>
<p><code>avcodec_init();</code></p>
<p><code>struct AVResampleContext* ctx = av_resample_init( ... );</code></p>
<p><code>av_resample( ctx, ... );</code></p>
<p><code> </code></p>
<p><code>av_resample_close( ctx );</code></p></blockquote>
<p>That&#8217;s it&#8230; seriously!</p>
<p><strong>Sample Code (Linux):</strong></p>
<p>Here&#8217;s a sample program I wrote that takes a raw 44.1kHz/16bit/mono audio file and plays it back using the <a title="Pulse Audio" href="http://pulseaudio.org/" target="_blank">pulseaudio</a> API. The catch is that it allows you to specify a &#8220;skew&#8221; parameter which will cause the audio to dynamically speed up and slow down (via resampling). The amount of resampling is controlled by a sine wave, which is what drives the speed changes.</p>
<p>Download:<strong> </strong><a title="Resample tar ball" href="http://www.tdistler.com/media/code/resample.tar.bz" target="_blank"><strong>resample.tar.bz</strong></a></p>
<p>To unpack and build, type:</p>
<blockquote><p><code>$ tar -xjvf resample.tar.bz<br />
$ make</code></p></blockquote>
<p>First, run the sample with no skew:</p>
<blockquote><p><code>$ ./resample audio_16b_44k_mono_pcm_raw 0</code></p></blockquote>
<p>Now, try it with a heavy skew:</p>
<blockquote><p><code>$ ./resample audio_16b_44k_mono_pcm_raw -10000</code></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2010/07/22/audio-resampling-using-ffmpeg-avcodec/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>ThreadNinja: Finding Rogue POSIX Threads</title>
		<link>http://tdistler.com/2010/07/08/threadninja-finding-rogue-posix-threads</link>
		<comments>http://tdistler.com/2010/07/08/threadninja-finding-rogue-posix-threads#comments</comments>
		<pubDate>Fri, 09 Jul 2010 02:10:04 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=277</guid>
		<description><![CDATA[What Is It? ThreadNinja is a Linux library my team created that tracks pthread_create() and pthread_join() calls in an application. It prints a stacktrace where each thread is created and where it is joined. Any rogue (unjoined) threads are reported when the application exits. ThreadNinja is unobtrusive: it does NOT have to be compiled into [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2010/05/tux-ninja.jpg"><img class="alignright size-thumbnail wp-image-278" title="tux-ninja" src="http://tdistler.com/wp-content/uploads/2010/05/tux-ninja-150x150.jpg" alt="Tux Ninja" width="150" height="150" /></a><strong>What Is It?</strong></p>
<p>ThreadNinja is a Linux library my team created that tracks <code>pthread_create()</code> and <code>pthread_join()</code> calls in an application. It prints a stacktrace where each thread is created and where it is joined. Any rogue (unjoined) threads are reported when the application exits. ThreadNinja is <em>unobtrusive</em>: it does NOT have to be compiled into the code. This means you can use it on applications you didn&#8217;t compile.</p>
<p>We found it useful and thought we&#8217;d share it. It&#8217;s be no means production code&#8230; just a tool. Hack on it, expand it, change it&#8230; whatever. It&#8217;s pretty small, so it should be easy to dive right in. We&#8217;ve released it under the <a title="BSD License Page" href="http://www.opensource.org/licenses/bsd-license.php" target="_blank">BSD license</a>.</p>
<p><strong>Cut To The Chase</strong></p>
<p>You can checkout the source code from <a title="Thread Ninja Project on Google Code" href="http://code.google.com/p/threadninja/" target="_blank">Google Code</a>, or download the version 1.0 tarball directly (<a title="Thread Ninja Source Tarball" href="http://www.tdistler.com/media/code/threadninja.tar.gz" target="_blank">threadninja.tar.gz</a>).</p>
<p>To build ThreadNinja, simply untar it and call <code>make</code>:<br />
<code>&gt; tar -zxf threadninja.tar.gz<br />
&gt; make</code></p>
<p>Now, simply use <code>LD_PRELOAD</code> to run the application:</p>
<p><code>&gt; LD_PRELOAD=/path/to/threadninja/build/libthreadninja.so.1 TheApplication</code></p>
<p>If you don&#8217;t see function names in the stacktraces that are generated, then the application needs to be compiled with debug symbols. For my test app, I had to compile with the <code>-rdynamic</code> option:</p>
<p><code>&gt; ﻿g++ -Wall -rdynamic main.cpp -lpthread</code></p>
<p>This causes the global symbol table to be included in the executable, which contains all the application&#8217;s function names. For more info, look at the <code>--export-dynamic</code> option on the <a title="GNU Linker man page" href="http://linux.die.net/man/1/ld" target="_blank">GNU linker (ld) man page</a>.</p>
<p><strong>The Story Behind ThreadNinja</strong></p>
<p>My team was assigned to stabilize a large video application that runs as a Linux-based appliance. The application consisted of 100,000+ of lines to code that was a tangle of build warnings, circular references, and many creative hacks. Our particular task was to fix a persistent set of seg-faults and memory leaks.<span id="more-277"></span></p>
<p>One of the first things we noticed was that the application didn&#8217;t shutdown properly. The shutdown logic was something akin to: signal components to exit, sleep 2 seconds, call Release() a couple times to clean up extra ref-counts, sleep 2 seconds, and then just call exit() to get the process to terminate (bypassing the remaining clean up code). Of course, this renders <a title="Valgrind" href="http://valgrind.org/" target="_blank">Valgrind</a> useless when trying to find memory leaks, because the automatic memory cleanup code gets bypassed during the process abort.</p>
<p>As a result, our first priority was to get the app to shutdown cleanly. The first issue we ran into was that <code>pthread_join()</code> blocked indefinitely because threads were failing to terminate. We tried using GDB to track the threads, but many hundreds of threads were being created and destroyed dynamically. We needed a way to let the application run for hours, allow 1000+ threads to live and die, and still be able to track rogue threads. Hence, ThreadNinja was born.</p>
<p><strong>How It Works</strong></p>
<p>Through the magic of <code><a title="LD_PRELOAD" href="http://linux.die.net/man/8/ld.so" target="_blank">LD_PRELOAD</a></code>, ThreadNinja &#8220;injects&#8221; itself between all calls to <code>pthread_create()</code> and <code>pthread_join()</code>. This happens because <code>LD_PRELOAD</code> instructs the loader to load ThreadNinja into memory first, before other libraries (in this case, before the pthread library). The result is that ThreadNinja&#8217;s implementation of <code>pthread_create()</code> and <code>pthread_join()</code> are used by the application instead of pthread&#8217;s own implementation. What ThreadNinja does is track the calls to these methods and then pass the call on to the &#8220;real&#8221; pthread implementation. From the application&#8217;s point-of-view, the behavior of the thread methods are the same&#8230; the tracking is transparent.</p>
<p><strong>Output</strong></p>
<p>Each time <code>pthread_create()</code> is called, a stacktrace and timestamp are printed to stdout:</p>
<p><code>Thread Created: 3047947120<br />
[bt] Thu Jul  8 16:31:23 2010</code></p>
<p><code>[bt] ./a.out(StartService(unsigned long*, int))<br />
[bt] ./a.out(Initialize())<br />
[bt] ./a.out(main+0xb) [0x80489fa]<br />
[bt] /lib/libc.so.6(__libc_start_main+0xe6) [0xb5bbb6]<br />
[bt] ./a.out() [0x8048811]</code></p>
<p>The first line (&#8220;Thread Created&#8221;) gives the value of the <code>pthread_t</code> handle, so you can later track where rogue threads where created. The next line is the time when the create happened. The remaining lines are the call stack that led to the <code>pthread_create()</code> call.</p>
<p>Each time <code>pthread_join()</code> is called, similar information is printed to stdout:</p>
<p><code>Thread Joined: 3047947120<br />
[bt] Thu Jul  8 16:31:31 2010</code></p>
<p><code>[bt] ./a.out(Terminate())<br />
[bt] ./a.out(main+0x10) [0x80489ff]<br />
[bt] /lib/libc.so.6(__libc_start_main+0xe6) [0xb5bbb6]<br />
[bt] ./a.out() [0x8048811]</code></p>
<p>When the application terminates (cleanly or uncleanly), a summary of the current state of the application threads is printed:</p>
<p><code>exit_handler()<br />
[Thread Summary]<br />
Total Created: 573<br />
Total Joined: 568<br />
Total Running: 5</code></p>
<p>In this case, you&#8217;ll notice that 5 threads were never joined on.</p>
<p><strong>Limitations</strong></p>
<p>ThreadNinja only tracks calls to <code>pthread_create()</code> and <code>pthread_join(</code>). This means calls like <code>system()</code>, <code>exec()</code>, and <code>fork()</code> are not tracked. Also, calls to <code>pthread_cancel()</code> are not tracked. We had started adding code to track pthread mutexes and stuff, but it turned out we didn&#8217;t need it. Feel free to add support for all this stuff and submit changes to the Google code site.</p>
<p>Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2010/07/08/threadninja-finding-rogue-posix-threads/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>High-performance Timing on Linux / Windows</title>
		<link>http://tdistler.com/2010/06/27/high-performance-timing-on-linux-windows</link>
		<comments>http://tdistler.com/2010/06/27/high-performance-timing-on-linux-windows#comments</comments>
		<pubDate>Mon, 28 Jun 2010 05:15:55 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=350</guid>
		<description><![CDATA[High-performance timing is hard… no doubt about it. I can’t tell you how many times I’ve seen high-performance timing code done wrong. Timing is one of those things where a little knowledge can be problematic; the code may work, but it either won’t perform or will exhibit “unexplained” behavior. The purpose of this post is [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2010/06/melting_clock.jpg"><img class="alignright size-full wp-image-352" title="melting_clock" src="http://tdistler.com/wp-content/uploads/2010/06/melting_clock.jpg" alt="Melting Clock" width="96" height="96" /></a>High-performance timing is hard… no doubt about it. I can’t tell you how many times I’ve seen high-performance timing code done wrong. Timing is one of those things where a little knowledge can be problematic; the code may work, but it either won’t perform or will exhibit “unexplained” behavior. The purpose of this post is to explain a foundational component to getting timing right: <em>the clock</em>. I won’t focus on theory… this post is meant to be pragmatic.</p>
<p><em>Note</em>: I’m talking here about interval timing (i.e. accurately measuring the duration between 2 events). This is different than synchronizing different clocks or maintaining accurate wall time.</p>
<p><strong>Anatomy of the Clock</strong></p>
<p>The first mistake most people make when doing timing is to use functions like <code><a href="http://www.opengroup.org/onlinepubs/000095399/functions/gettimeofday.html" target="_blank">gettimeofday()</a></code>, <code><a title="MSDN: GetSystemTime" href="http://msdn.microsoft.com/en-us/library/ms724390(VS.85).aspx" target="_blank">GetSystemTime()</a></code>, etc. These functions return what is called &#8220;wall time&#8221;… time that corresponds to a calendar date/time. These clocks suffer from the follow limitations:</p>
<ol>
<li>They have a low resolution: “High-performance” timing, by my definition, requires clock resolutions into the microseconds or better.</li>
<li>They can jump forwards and backwards in time: Computer clocks all tick at slightly different rates, which causes the time to drift. Most systems have NTP enabled which periodically adjusts the system clock to keep them in sync with “actual” time. The adjustment can cause the clock to suddenly jump forward (artificially inflating your timing numbers) or jump backwards (causing your timing calculations to go negative or hugely positive).</li>
</ol>
<p>For interval timing, all that’s needed for a clock is a simple counter that increments at a stable rate. For high-performance timing, the rate this counter increments should be high. A related constraint is that the counter must be monotonic (can never “tick” backwards&#8230; ever). The counter may overflow and wrap back to 0, but using unsigned math in your timing calculations can compensate for that (see example below).</p>
<p>Something to note: since we are usually measuring short durations, the drift of the clock is so small that we aren&#8217;t concerned by it (what matters is the drift between successive reads, not total drift over time).<span id="more-350"></span></p>
<p><strong>Using the Clock</strong></p>
<p>To use the clock, you need access to 2 pieces of information: the clock value, and the rate (frequency) at which it increments. Once you have that information, it’s trivial to calculate the duration between 2 successive reads of the clock.</p>
<p>For example, consider the following:</p>
<p>-        <code>start</code> equals the clock value at the beginning of the interval to measure.</p>
<p>-        <code>end</code> equals the clock value at the end of the interval.</p>
<p>-        <code>frequency</code> equals the frequency that the clock increments per second.</p>
<p>Calculating the duration of the interval (in seconds) is as simple as:</p>
<p><code>duration = (end – start) / frequency</code></p>
<p><code>duration</code> will equal the floating-point interval time in seconds (e.g. 0.000237 = 237us).</p>
<p>A common use case I’ve seen is wanting to measure the duration between successive calls to a function. Here’s one way to implement that:</p>
<pre><code>float freq = (float) get_frequency();

Foo()
{
    unsigned now = read_clock();
    float duration = (float)(now – last) / (float)freq;
    last = now;

    /* Your code here */
}
</code></pre>
<p>It is important to use unsigned variables for <code>now</code> and <code>last</code> or your calculations will go haywire if the clock ever wraps back to 0. Consider what happens if <code>now</code> is less than <code>last</code>. Using unsigned variables allows the math operation to underflow, which produces the correct result. If you don&#8217;t believe me, just write some test code and see for yourself&#8230; it&#8217;s an important concept to understand.</p>
<p><strong>Don’t Use RDTSC As Your Clock</strong></p>
<p>I’m dismayed by how many forum posts suggest that newbie’s use <a title="Wikipedia: RDTSC" href="http://en.wikipedia.org/wiki/RDTSC" target="_blank">RDTSC</a> for timing. Don’t get me wrong; the TSC isn’t bad in-and-of-itself. It’s just way too hard to get timing right with it unless you’re an expert… and if you’re reading this, chances are you aren’t <img src='http://tdistler.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Stick to the higher level API’s I present below.</p>
<p>Even if you are an expert, I still suggest avoiding RDTSC for the following reasons:</p>
<ol>
<li>It’s processor core specific: Using RDTSC will give different values on different processor cores. This causes non-monotonic clock behavior as a thread is migrated across cores during execution (i.e. the clock can tick backwards on two successive reads). Conversely, the clock may also appear to jump forwards if the thread moves to a different core.</li>
<li>It doesn’t always tick at the same rate: On some systems, the clock frequency will vary as the CPU load changes. This is due to power saving features in the processor that throttle down the clock speed when the load is low (e.g. Intel SpeedStep).</li>
<li>It’s unnecessary: there are better alternatives to RDTSC that are readily available (<a title="Wikipedia: High Precision Event Timer" href="http://en.wikipedia.org/wiki/High_Precision_Event_Timer" target="_blank">HPET</a> and <a title="Wikipedia: Advanced Programmable Interrupt Controller" href="http://en.wikipedia.org/wiki/Advanced_Programmable_Interrupt_Controller" target="_blank">APIC</a>).</li>
</ol>
<p>“<a title="Game Timing and Multicore Processors" href="http://msdn.microsoft.com/en-us/library/ee417693(VS.85).aspx" target="_blank">Game Timing and Multicore Processors</a>” has more info, though it’s centered around Windows.</p>
<p>“<a title="Guidelines For Providing Multimedia Support" href="http://www.microsoft.com/whdc/system/sysinternals/mm-timer.mspx" target="_blank">Guidelines For Providing Multimedia Support</a>” has a good summary of the hardware clocks on the PC platform, and justification for the creation of the HPET.</p>
<p>A more technical look into the past problems with RDTSC can be found in <a title="Email from Rick Brunner" href="http://lkml.org/lkml/2005/11/4/173" target="_blank">this email from Rick Brunner (AMD Fellow)</a>.</p>
<p>If you&#8217;re having trouble sleeping, you can look at <a title="Intel: HPET Design" href="http://www.intel.com/hardwaredesign/hpetspec_1.pdf" target="_blank">Intel’s HPET design document</a>.</p>
<p><strong>Linux Clock</strong></p>
<p>POSIX.1b defines realtime clock methods that you’ll find on most *NIX systems (the full spec can be viewed <a title="POSIX Specification 2008" href="http://www.opengroup.org/onlinepubs/9699919799/" target="_blank">HERE</a>). Specifically, you want to use <code>clock_getres()</code> and <code>clock_gettime()</code>. <code>clock_getres()</code> returns the resolution (frequency) of the clock, and <code>clock_gettime()</code> returns the current value of the clock. Most systems implement the <code>CLOCK_MONOTONIC</code> type, which provides a frequency-stable, monotonically-increasing counter. The resolution of <code>CLOCK_MONOTONIC</code> is high on the 2.6 kernel, in my experience. I recommend using this clock when building a high-performance timing solutions on Linux.</p>
<p>The methods are defined in <code>time.h</code>, and you need to link against librt (pass ‘-lrt’ to gcc). The prototypes for the functions are:</p>
<p><code>int clock_getres(clockid_t <em>clock_id</em>, struct timespec *<em>res</em>);</code><br />
<code>int clock_gettime(clockid_t <em>clock_id</em>, struct timespec *<em>tp</em>);</code></p>
<p>A detailed description of these methods can be found <a href="http://www.opengroup.org/onlinepubs/000095399/functions/clock_getres.html" target="_blank">HERE</a>.</p>
<p>I also suggest looking at <code><a href="http://www.opengroup.org/onlinepubs/000095399/functions/clock_nanosleep.html" target="_blank">clock_nanosleep()</a></code>, but that’s a separate topic.</p>
<p><strong>Windows Clock</strong></p>
<p>On Windows, <code><a href="http://msdn.microsoft.com/en-us/library/ms644905(VS.85).aspx" target="_blank">QueryPerformanceFrequency()</a></code> and <code><a href="http://msdn.microsoft.com/en-us/library/ms644904(v=VS.85).aspx" target="_blank">QueryPerformanceCounter()</a></code> are the obvious choice. <code>QueryPerformanceFrequency()</code> returns (surprise!) the frequency of the counter. <code>QueryPerformanceCounter()</code> returns the current value of the counter. Just like <code>CLOCK_MONOTONIC</code> on Linux, the Windows performance counter is a high-frequency, stable, monotonically-increasing counter.</p>
<p>The methods are defined in <code>windows.h</code>. The prototypes are:</p>
<p><code>BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);<br />
BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)</code>;</p>
<p><strong>Windows Timing Errata</strong></p>
<p><em>Note</em>: The follow items do NOT affect the resolution of the Window’s performance counter, but I think it’s still important to know when doing timing on Windows.</p>
<p>One problem you may run into on Windows is that the default system clock interval defaults to 10 or 15ms (depending of the OS version). This clock is what drives all the timers and sleep functions for that platform. What this means is that, left to the default, your timers will trigger 5 to 7.5ms late, on average.</p>
<p>You can fix this by increasing the system clock resolution to 2ms (I remember reading a tech article by Microsoft saying that 2ms gave better system performance than 1ms, but I can’t find it for the life of me). You do this by using the <code>timeGetDevCaps()</code>, <code>timeBeginPeriod()</code> and <code>timeEndPeriod()</code>. Sample code can be found <a title="Windows Multimedia Timers" href="http://msdn.microsoft.com/en-us/library/dd743626(v=VS.85).aspx" target="_blank">HERE</a>. You have to include <code>mmsystem.h</code> and link against <code>Winmm.lib</code>.</p>
<p>I feel it necessary to note that increasing the system clock interval negatively affects power consumption. The Windows 7 blog as an interesting breakdown of “<a title="Windows 7 Energy Efficiency" href="http://blogs.msdn.com/b/e7/archive/2009/01/06/windows-7-energy-efficiency.aspx" target="_blank">Windows 7 Energy Efficiency</a>”. Specifically, they noticed a 10% drop in battery life when the clock resolution was set to 1ms using <code>timeBeginPeriod()</code>.</p>
<p>Maybe this last section belongs in a separate post, but whatever&#8230; <img src='http://tdistler.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2010/06/27/high-performance-timing-on-linux-windows/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stop Stealing My File Descriptors!</title>
		<link>http://tdistler.com/2010/06/18/stop-stealing-my-file-descriptors</link>
		<comments>http://tdistler.com/2010/06/18/stop-stealing-my-file-descriptors#comments</comments>
		<pubDate>Fri, 18 Jun 2010 21:48:43 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=313</guid>
		<description><![CDATA[We ran into a weird problem the other day where our Linux video display appliance would lose audio support when the process was restarted. The audio was supposed to play through a custom joystick-keyboard that was attached via USB (the keyboard is used by security guards to PTZ cameras, control monitors, etc). The audio could [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2010/06/sherlock_tux.jpg"><img class="alignright size-thumbnail wp-image-319" title="sherlock_tux" src="http://tdistler.com/wp-content/uploads/2010/06/sherlock_tux-150x150.jpg" alt="Sherlock Tux" width="150" height="150" /></a>We ran into a weird problem the other day where our Linux video display appliance would lose audio support when the process was restarted. The audio was supposed to play through a custom joystick-keyboard that was attached via USB (the keyboard is used by security guards to PTZ cameras, control monitors, etc). The audio could be heard just fine when the box first booted, but if the application restarted audio would be lost.</p>
<p>Looking at the logs, we found that our audio pipeline was failing to open <code>/dev/dsp</code> on the restart. We then used <code>lsof</code> to list the open file descriptors to see which process currently held <code>/dev/dsp</code>:</p>
<p><code># lsof | grep /dev/dsp<br />
ntpd   18857    root   16u    CHR     14,3    180099 /dev/dsp<br />
</code></p>
<p>What!?!?&#8230; why the heck is NTP opening the sound device and how did it steal it from us??? After some discussion we started remembering a problem in the past with <code>ntpd</code> stealing our SNMP diagnostics port. This just didn&#8217;t make any sense.</p>
<p>Digging into our appliance code, we found this line:</p>
<p><code>system( "service ntpd restart" );</code></p>
<p>This would be called each time we were notified by the security system that the NTP server address had changed (which fired once each time the process was started so we could get the initial address). But this still didn&#8217;t explain why NTP took over ownership of our file descriptors on restart.</p>
<p>Long story short: <code>system()</code> is implemented as <code>fork()</code> followed by <code>execv()</code>. By default, <code>fork()</code> gives a copy of the parent&#8217;s file descriptors to the child process (i.e. the <code>ntpd</code> child process got a copy of the <code>/dev/dsp</code> file descriptor). To prevent this, you have to set the <code>FD_CLOEXEC</code> flag on the file desciptors you don&#8217;t want copied.</p>
<p>For example:</p>
<p><code>fd = open( "/dev/dsp", O_RDWR );<br />
fcntl( fd, F_SETFD, FD_CLOEXEC );</code></p>
<p><strong>Conclusion</strong>: setting the <code>FD_CLOEXEC</code> flag on the <code>/dev/dsp</code> file descriptor fixed the problem for audio. However, most of the other file desciptors still got owned by <code>ntpd</code>. Did we go back and set the <code>FD_CLOEXEC</code> flag on all file descriptors, you ask? Nope. It turns out we had a script monitoring the NTP config file and restarting ntpd for us when the file got updated&#8230; we just had to update the config file and remove the <code>system( "service ntpd restart" )</code> call.</p>
<p>Oh, and the reason audio worked on first boot but not subsequent restarts was due to a weird race condition around when <code>/dev/dsp</code> got opened.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2010/06/18/stop-stealing-my-file-descriptors/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sed Regular Expression: Find Lines Not Matching A String</title>
		<link>http://tdistler.com/2009/04/17/sed-regular-expression-find-lines-not-matching-a-string</link>
		<comments>http://tdistler.com/2009/04/17/sed-regular-expression-find-lines-not-matching-a-string#comments</comments>
		<pubDate>Fri, 17 Apr 2009 23:39:49 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=218</guid>
		<description><![CDATA[After some digging, I finally found out how to create a regex for Sed (stream editor) that will find a line that does NOT contain a particular string. First, I used &#8216;find&#8217; to list all the *.cpp files in my source tree: find . -name &#8220;*.cpp&#8221; -print Then I piped the files to &#8216;sed&#8217; via [...]]]></description>
			<content:encoded><![CDATA[<p>After some digging, I finally found out how to create a regex for Sed (stream editor) that will find a line that does NOT contain a particular string. First, I used &#8216;find&#8217; to list all the *.cpp files in my source tree:</p>
<p class="codeblock">find . -name &#8220;*.cpp&#8221; -print</p>
<p>Then I piped the files to &#8216;sed&#8217; via &#8216;xargs&#8217; (Note: replace the &#8216;-e&#8217; with &#8216;-i&#8217; to actually modify the files inline):</p>
<p class="codeblock">find . -name &#8220;*.cpp&#8221; -print | xargs sed -e &#8216;/STRING_TO_INGORE/! { d }&#8217;</p>
<p>The trick is adding the &#8216;!&#8217; (exclamation point) after the search expression. Without it, &#8216;sed&#8217; would think you only want lines <em>with</em> the string, not <em>without</em> it.</p>
<p>This is different than another syntax I&#8217;ve seen used: /(?!STRING_TO_IGNORE)/.</p>
<p>Here&#8217;s another example. Say you want to replace STRING1 with STRING2 only if the first characters of the line (ignoring white space)  are NOT &#8220;//&#8221;&#8230; i.e. skip the string replacement in code comments:</p>
<p class="codeblock">sed -i &#8216;/^[ \t]*\/\/.*/! { s/STRING1/STRING2/ }&#8217;</p>
<p>NOTE: &#8216;[ \t]*&#8217; means ignore 0 or more spaces or tabs.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2009/04/17/sed-regular-expression-find-lines-not-matching-a-string/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Find &amp; Replace in Files on Linux</title>
		<link>http://tdistler.com/2009/04/13/find-replace-in-files-on-linux</link>
		<comments>http://tdistler.com/2009/04/13/find-replace-in-files-on-linux#comments</comments>
		<pubDate>Mon, 13 Apr 2009 19:28:59 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=200</guid>
		<description><![CDATA[A lot of solutions I&#8217;ve found for recursively replacing text in files is implemented using shell scripts, perl, php, or some other inconvenient way. Rushi got it right by using the Linux command line. Here it is (slightly modified) from his blog: find . -name &#8220;*.cpp&#8221; -print &#124; xargs sed -i &#8216;s/[find]/[replace]/g&#8217; where &#8220;[find]&#8221; and [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" style="float: right;" src="/media/images/tux.jpg" alt="Tux" />A lot of solutions I&#8217;ve found for recursively replacing text in files is implemented using shell scripts, perl, php, or some other inconvenient way. <a href="http://rushi.vishavadia.com/blog/2008/08/05/find-replace-across-multiple-files-in-linux/" target="_blank">Rushi</a> got it right by using the Linux command line. Here it is (slightly modified) from his blog:</p>
<p class="codeblock">find . -name &#8220;*.cpp&#8221;  -print | xargs sed -i &#8216;s/[find]/[replace]/g&#8217;</p>
<p>where &#8220;[find]&#8221; and &#8220;[replace]&#8221; are the things you are searching for and substituting.</p>
<p>To search files with multiple file extensions, use:</p>
<p class="codeblock">find . -name &#8220;*.cpp&#8221;  -o -name &#8220;*.h&#8221; -o -name &#8220;*.c&#8221; | xargs sed -i &#8216;s/[find]/[replace]/g&#8217;</p>
<p><b>ADDED 4-13-2009:</b> See comments for other variations.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2009/04/13/find-replace-in-files-on-linux/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to Recursively Delete Subversion .svn Directories</title>
		<link>http://tdistler.com/2009/03/17/how-to-recursively-delete-subversion-svn-directories</link>
		<comments>http://tdistler.com/2009/03/17/how-to-recursively-delete-subversion-svn-directories#comments</comments>
		<pubDate>Tue, 17 Mar 2009 22:13:03 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=153</guid>
		<description><![CDATA[Ok, some posts are clearly just to help me remember how to do things&#8230; this is one of them. The Subversion source control system keeps private information in .svn directories. There is one such directory for EVERY directory in your source tree. Here&#8217;s how you recursively delete ALL the .svn directories from the current directory [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" style="float: right;" src="/media/images/subversion_logo.jpg" alt="Subversion Logo" />Ok, some posts are clearly just to help me remember how to do things&#8230; this is one of them. The <a title="Subversion" href="http://subversion.tigris.org/" target="_blank">Subversion</a> source control system keeps private information in .svn directories. There is one such directory for EVERY directory in your source tree. Here&#8217;s how you recursively delete ALL the .svn directories from <b><em>the current directory</em></b> in Linux (or <a title="Cygwin" href="http://www.cygwin.com/" target="_blank">Cygwin</a> in Windows).</p>
<p class="codeblock">rm -rf `find . -type d -name .svn`</p>
<p>NOTE: Those are back ticks around the &#8216;find&#8217; command, not apostrophes. I recommend you just run the &#8216;find&#8217; command first and verify it is listing the directories you expect.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2009/03/17/how-to-recursively-delete-subversion-svn-directories/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to Print a Stack Backtrace Programatically in Linux</title>
		<link>http://tdistler.com/2008/11/15/how-to-print-a-stack-backtrace-programatically-in-linux</link>
		<comments>http://tdistler.com/2008/11/15/how-to-print-a-stack-backtrace-programatically-in-linux#comments</comments>
		<pubDate>Sun, 16 Nov 2008 00:36:58 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=149</guid>
		<description><![CDATA[So here&#8217;s a cool feature of GNU&#8217;s implementation of libc: you can get a stack backtrace (as an array of strings) dynamically in your code. This can be really useful when trying to determine the code path taken when an error occurs. Most times, it&#8217;s faster to just run the code in a debugger and [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" style="float: right;" src="/media/images/GNULogo.jpg" alt="GNU Logo" />So here&#8217;s a cool feature of <a title="GUN libc" href="http://www.gnu.org/software/libc/" target="_blank">GNU&#8217;s implementation of libc</a>: you can get a stack backtrace (as an array of strings) dynamically in your code. This can be really useful when trying to determine the code path taken when an error occurs. Most times, it&#8217;s faster to just run the code in a debugger and use it to display a backtrace, but there are instances when doing it programmatically is your best option. For example, you could get a backtrace in your application&#8217;s exception handler and use it to augment error log messages.</p>
<p>First, you need to include execinfo.h to your code:</p>
<p><code>#include &lt;execinfo.h&gt;</code></p>
<p>Next, call the <code>backtrace()</code> function to get an array of void pointers that represents the current stack (the pointers are the return addresses for each stack frame).</p>
<p><code>void* tracePtrs[100];<br />
int count = backtrace( tracePtrs, 100 );</code></p>
<p>The <code>backtrace()</code> function returns the number of entries in the array (read the man pages for more info about the array size).</p>
<p>Finally, you need to resolve the function names associated with the pointers. You have 2 options: <code>backtrace_symbols()</code> and <code>backtrace_symbols_fd()</code>. Both of these methods resolve the pointers to strings, but the difference is that <code>backtrace_symbols()</code> allocates the strings on the heap while <code>backtrace_symbols_fd()</code> writes the strings to a file descriptor that you can read. Just keep in mind that <code>backtrace_symbols()</code> won&#8217;t work if the heap has been trashed.</p>
<p>Here&#8217;s an example using <code>backtrace_symbols()</code>:</p>
<pre><code>char** funcNames = backtrace_symbols( tracePtrs, count );

// Print the stack trace
for( int ii = 0; ii &lt; count; ii++ )
    printf( "%s\n", funcNames[ii] );

// Free the string pointers
free( funcNames );</code></pre>
<p><br/>NOTE: Make sure you call <code>free()</code> on the array of strings returned from <code>backtrace_symbols()</code>.</p>
<p>For more information, <a title="Linux Journal: Stack Backtraceing Inside Your Program" href="http://www.linuxjournal.com/article/6391" target="_blank">here&#8217;s a good article from the Linux Journal</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2008/11/15/how-to-print-a-stack-backtrace-programatically-in-linux/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Image: Powered By GNU/Linux</title>
		<link>http://tdistler.com/2008/11/14/image-powered-by-gnulinux</link>
		<comments>http://tdistler.com/2008/11/14/image-powered-by-gnulinux#comments</comments>
		<pubDate>Fri, 14 Nov 2008 19:46:17 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Oh So Random]]></category>
		<category><![CDATA[Tech and Security]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=147</guid>
		<description><![CDATA[I saw a Linux logo I liked on Google Images a while back, but all instances of it have been removed. I got tired of searching, so last night I hacked around in Photoshop and recreated it. 500 x 750 JPEG 500 x 750 PNG]]></description>
			<content:encoded><![CDATA[<p>I saw a Linux logo I liked on Google Images a while back, but all instances of it have been removed. I got tired of searching, so last night I hacked around in Photoshop and recreated it.</p>
<p style="text-align: center;"><img style="vertical-align: middle;" src="/media/images/PoweredByGNULinuxSmall.jpg" alt="Powered By GNU/Linux thumbnail" /></p>
<ul>
<li><a title="Powered By GNU/Linux JPEG" href="/media/images/PoweredByGNULinux.jpg" target="_blank">500 x 750 JPEG</a></li>
<li><a title="Powered By GNU/Linux PNG" href="/media/images/PoweredByGNULinux.png" target="_blank">500 x 750 PNG</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2008/11/14/image-powered-by-gnulinux/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Debugging: C++ Templates, Breakpoints, and GDB</title>
		<link>http://tdistler.com/2008/11/13/debugging-c-templates-brekpoints-and-gdb</link>
		<comments>http://tdistler.com/2008/11/13/debugging-c-templates-brekpoints-and-gdb#comments</comments>
		<pubDate>Fri, 14 Nov 2008 01:28:57 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=146</guid>
		<description><![CDATA[Debugging C++ templates is difficult. Debugging C++ templates with GDB can be an act of torture for even seasoned GDB users. I like GDB, but there are some tricks you should know when using it to debug templates. In this post, I deal with setting breakpoints. Breakpoint Basics: Setting a breakpoint in GDB is supposed [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" style="float: right;" src="/media/images/GNULogo.jpg" alt="GNU Logo" />Debugging C++ templates is difficult. Debugging C++ templates with GDB can be an act of torture for even seasoned GDB users. I like GDB, but there are some tricks you should know when using it to debug templates. In this post, I deal with setting breakpoints.</p>
<p><strong>Breakpoint Basics:</strong></p>
<p>Setting a breakpoint in GDB is supposed to be simple. Here we set a breakpoint at line 50 in file main.cpp:</p>
<p class="codeblock">(gdb) b main.cpp:50<br />
Breakpoint 1 at 0x804937a: file main.cpp, line 50.</p>
<p>We can also use the function name and GDB will attempt to find the correct location for us:</p>
<p class="codeblock">(gdb) b DoSomething<br />
Breakpoint 2 at 0&#215;8049334: file main.cpp, line 150</p>
<p>Simple, right? Just wait&#8230;</p>
<p><strong>Breakpoint Gotchas:</strong></p>
<p>GDB&#8217;s breakpoint logic is pretty handy for simple projects, but it can break down fast when things get more complicated.</p>
<p>For example, let&#8217;s say your application is plugin-driven, with each plugin being a separate library. Now assume each plugin has a Plugin.cpp file under it&#8217;s own Source directory. Try to set a breakpoint in the Initialize() method of the Plugin class:</p>
<p class="codeblock">(gdb) b Initialize<br />
Breakpoint 3 at 0&#215;8049717: file main.cpp, line 230</p>
<p>Oops! There is an Initialize() method in main.cpp and GDB thought that&#8217;s where we wanted to put it: wrong!</p>
<p><span id="more-146"></span>Okay, let&#8217;s be more specific:</p>
<p class="codeblock">(gbd) b Plugin::Initialize<br />
Breakpoint 4 at 0&#215;8046194: file Source/Plugin.cpp, line 89</p>
<p>Okay, that looks better, but <em>which </em>Plugin.cpp file did GDB put the breakpoint? How do we know it&#8217;s the file for the plugin we want?</p>
<p>If we used namespaces, then we can get more specific:</p>
<p class="codeblock">(gdb) b MY_PLUGIN_A::Plugin::Initialize<br />
Breakpoint 5 at 0&#215;8050039: file Source/Plugin.cpp, line 130</p>
<p>We can see from the address and line number that the previous breakpoint was at the wrong place. Okay, moving on&#8230;</p>
<p><strong>Setting Breakpoint in Templates:</strong></p>
<p>Templates can be much harder to set breakpoints in because we have to specify the <em>exact </em>prototype for the fully-defined template. We as programmers are used to the compiler handling the template type stuff for us, so it can be difficult to guess the correct type.</p>
<p>For example, assume we have some abstract class BarAbstract that uses the template Foo&lt;&gt; to make it concrete. Now assume we&#8217;re really clever and we want to hide this from the users of our class. We could use a typedef to hide the true type:</p>
<p class="codeblock">typedef Foo&lt;BarAbstract&gt; Bar;</p>
<p>Now, all the user needs to do is instantiate Bar without a thought to the Foo&lt;&gt; template.</p>
<p class="codeblock">int DoSomething()<br />
{<br />
Bar b;<br />
return b.Baz();<br />
}</p>
<p>So far so good? Okay, now how the heck do you set a breakpoint in the Baz() method of class Bar?</p>
<p>The quick answer: use objdump, c++filt, and grep to find the complete definition that GDB will need.</p>
<p class="codeblock">$ objdump -t libMyLib.so | c++filt | grep &#8216;BarAbstract.*Baz&#8217;<br />
0000d2d6 w F .text 0000000a     MY_PLUGIN_A::Foo&lt;MY_PLUGIN_A::BarAbstract&gt;::Baz()</p>
<p>Now, simply copy-n-paste the full method definition to GDB when setting the breakpoint:</p>
<p class="codeblock">(gdb) b MY_PLUGIN_A::Foo&lt;MY_PLUGIN_A::BarAbstract&gt;::Baz()<br />
Breakpoint 6 at 0&#215;8048890: file Source/Bar.cpp, line 355</p>
<p>That&#8217;s it! Happy debugging!</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2008/11/13/debugging-c-templates-brekpoints-and-gdb/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Enabling X Server Remote Connections on Fedora 9</title>
		<link>http://tdistler.com/2008/11/11/enabling-x-server-remote-connections-on-fedora-9</link>
		<comments>http://tdistler.com/2008/11/11/enabling-x-server-remote-connections-on-fedora-9#comments</comments>
		<pubDate>Tue, 11 Nov 2008 21:38:26 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Tech and Security]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=145</guid>
		<description><![CDATA[Recently, I was trying to run a GUI front-end to Valgrind (Valkyrie) from within a chroot&#8217;d environment on Fedora 9. It failed to run, and after some searching I figured out the problem. Here&#8217;s the story. First, I made sure to disable access control from outside the chroot (warning: make sure you understand the security [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" style="float: right;" src="/media/images/Fedora_Logo.gif" alt="Fedora Logo" />Recently, I was trying to run a GUI front-end to <a title="Valgrind" href="http://valgrind.org/" target="_blank">Valgrind</a> (<a title="Valkyrie" href="http://www.open-works.net/projects/valkyrie.html" target="_blank">Valkyrie</a>) from within a chroot&#8217;d environment on <a title="Fedora" href="http://fedoraproject.org/" target="_blank">Fedora</a> 9. It failed to run, and after some searching I figured out the problem. Here&#8217;s the story.</p>
<p>First, I made sure to disable access control from outside the chroot (warning: make sure you understand the security implications of this!):</p>
<p class="codeblock">[dev]$ xhost + localhost<br />
localhost being added to access control list</p>
<p>Next, I entered the chroot&#8217;d environment and attempted to run the application, but it failed with the following error:</p>
<p class="codeblock">[chroot]$ valkyrie<br />
valkyrie: cannot connect to X server 127.0.0.1:0.0</p>
<p>The problem is that the X server is configured by default NOT to listen for remote connections (usually on port 6000). I verified that this was the problem by leaving the chroot and trying to connect via telnet:</p>
<p class="codeblock">[dev]$ telnet 127.0.0.1 6000<br />
Trying 127.0.0.1&#8230;<br />
telnet: connect to address 127.0.0.1: Connection refused</p>
<p>The way to fix this on previous Fedora installations was to use gdmsetup. However, this is no longer available. Hunting through the KDE config files I found the solution: change the arguments passed to the X server after login in the kdmrc file. </p>
<p><b>NOTE</b>: I&#8217;m using <a title="fluxbox" href="http://fluxbox.org/" target="_blank">fluxbox</a> as my desktop environment&#8230; KDE is used for the Fedora login screen, which is why we are messing with its config files.</p>
<p class="codeblock">[dev]$ sudo su<br />
[root]# cd /etc/kde/kdm<br />
[root]# cp kdmrc kdmrc.old<br />
[root]# vi kdmrc</p>
<p>On my system, the problem was this line:</p>
<p class="codeblock">ServerArgsLocal=-br -nolisten tcp</p>
<p>I simply changed it to:</p>
<p class="codeblock">ServerArgLocal=-br</p>
<p>I restarted my X server and tried to connect with telnet again (this time with success):</p>
<p class="codeblock">[dev]$ telnet 127.0.0.1 6000<br />
Trying 127.0.0.1&#8230;<br />
Connected to 127.0.0.1.<br />
Escape character is &#8216;^]&#8217;.</p>
<p>Then, I once again disabled X access control (`xhost + localhost`) and everything worked fine. Hope this helps!</p>
<p><b>EDITED 11/17/2008:</b> Changed &#8216;xhost +&#8217; to &#8216;xhost + localhost&#8217;</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2008/11/11/enabling-x-server-remote-connections-on-fedora-9/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Setting the DHCP Hostname on Linux</title>
		<link>http://tdistler.com/2008/10/14/setting-the-dhcp-hostname-on-linux</link>
		<comments>http://tdistler.com/2008/10/14/setting-the-dhcp-hostname-on-linux#comments</comments>
		<pubDate>Tue, 14 Oct 2008 22:59:27 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[network]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=141</guid>
		<description><![CDATA[I&#8217;m always forgetting how to register my machine name with the DHCP server so I can ping my box without having to remember my IP address. Here&#8217;s how to do it on Fedora Core 9: Set the hostname: `# hostname &#60;hostname&#62;` Add &#8216;HOSTNAME=&#60;hostname&#62;&#8217; to &#8216;/etc/sysconfig/network&#8217; (makes the change permanent). Add &#8216;DHCP_HOSTNAME=&#60;hostname&#62;&#8217; to &#8216;/etc/sysconfig/network-scripts/ifcfg-eth0&#8242; Restart the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m always forgetting how to register my machine name with the DHCP server so I can ping my box without having to remember my IP address. Here&#8217;s how to do it on Fedora Core 9:</p>
<ol>
<li>Set the hostname: `# hostname &lt;<em>hostname</em>&gt;`</li>
<li>Add &#8216;HOSTNAME=&lt;<em>hostname</em>&gt;&#8217; to &#8216;/etc/sysconfig/network&#8217; (makes the change permanent).</li>
<li>Add &#8216;DHCP_HOSTNAME=&lt;<em>hostname</em>&gt;&#8217; to &#8216;/etc/sysconfig/network-scripts/ifcfg-eth0&#8242;</li>
<li>Restart the networking service: `# service network restart`</li>
</ol>
<p>Volia! Now you can connect to your box via hostname.</p>
<p>References:</p>
<ul>
<li><a title="nixCraft" href="http://www.cyberciti.biz/faq/howto-get-linux-static-dhcp-address/" target="_blank">Configuring Linux Static DHCP Clients by Sending Host Name</a></li>
<li><a title="nixCraft" href="http://www.cyberciti.biz/faq/linux-setting-hostname-and-domain-name-of-my-server/" target="_blank">Linux setting hostname and domain name of my server</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2008/10/14/setting-the-dhcp-hostname-on-linux/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>YouTube&#8217;s Architecture and Scalability</title>
		<link>http://tdistler.com/2008/07/23/youtubes-architecture-and-scalability</link>
		<comments>http://tdistler.com/2008/07/23/youtubes-architecture-and-scalability#comments</comments>
		<pubDate>Wed, 23 Jul 2008 14:36:54 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Tech and Security]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=127</guid>
		<description><![CDATA[High Scalability has a great link to a video TechTalk with Cuong Do, YouTube&#8217;s engineering manager. He talks about the challenges YouTube faces (past and present) to meet it&#8217;s skyrocketing user demand, as well as the infrastructure that allows them to scale. I enjoyed the anecdotes: especially the frantic email sent at 2am alerting the [...]]]></description>
			<content:encoded><![CDATA[<p><a title="High Scalability" href="http://highscalability.com" target="_blank">High Scalability</a> has a great link to a video <a title="YouTube: Google Tech Talks" href="http://youtube.com/user/googletechtalks" target="_blank">TechTalk</a> with Cuong Do, <a title="YouTube" href="http://youtube.com/" target="_blank">YouTube&#8217;s</a> engineering manager. He talks about the challenges YouTube faces (past and present) to meet it&#8217;s skyrocketing user demand, as well as the infrastructure that allows them to scale. I enjoyed the anecdotes: especially the frantic email sent at 2am alerting the dev team that they only had 3 days of storage left&#8230; I always thought Google/YouTube would be immune to emergencies like that&#8230; ignorance on my part <img src='http://tdistler.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  </p>
<p style="text-align: center;"><object type="application/x-shockwave-flash" data="http://www.youtube.com/v/ZW5_eEKEC28&amp;hl=en" width="425" height="355"><param name="movie" value="http://www.youtube.com/v/ZW5_eEKEC28&amp;hl=en" /><param name="FlashVars" value="playerMode=embedded" /><param name="wmode" value="transparent" /></object></p>
<p style="text-align: center;">(requires <a href="http://www.adobe.com/products/flashplayer/" target="_blank">Adobe Flash</a> plugin&#8230; click <a href="http://www.youtube.com/watch?v=ZW5_eEKEC28" target="_blank">HERE</a> to watch it on YouTube)</p>
<p>I found this information interesting:</p>
<ul>
<li>The application code is written mostly in <a title="Python" href="http://www.python.org/" target="_blank">Python</a> (the web app is not the bottleneck&#8230; the database RPC is)</li>
<li>They use <a title="Apache Webserver" href="http://httpd.apache.org/" target="_blank">Apache</a> for page content and <a title="lighttpd Webserver" href="http://www.lighttpd.net/" target="_blank">lighttpd</a> for serving video</li>
<li>Thumbnails are now served by <a title="Wikipedia: Google BitTable" href="http://en.wikipedia.org/wiki/BigTable" target="_blank">Google&#8217;s BigTable</a></li>
<li>They&#8217;re running <a title="SuSE Linux" href="http://www.novell.com/linux/" target="_blank">SuSE</a> Linux with <a title="MySQL" href="http://www.mysql.com/" target="_blank">MySQL</a></li>
<li>HW <a title="Wikipedia: RAID" href="http://en.wikipedia.org/wiki/Redundant_array_of_independent_disks" target="_blank">RAID</a>-10 across multiple disks was too slow. HW RAID-1 with SW RAID-0 was faster because the Linux I/O scheduler could see the multiple volumes and would therefore schedule more I/O</li>
</ul>
<p>You can read a good summary of the talk <a title="High Scalability: YouTube Architecture" href="http://highscalability.com/youtube-architecture" target="_blank">HERE</a> from the High Scalability website.</p>
<p><a title="Tech Crunch: YouTube: The Platform" href="http://www.techcrunch.com/2008/03/12/youtube-the-platform/" target="_blank">TechCruch</a> has a good article of the <a title="YouTube" href="http://youtube.com/" target="_blank">YouTube</a> API.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2008/07/23/youtubes-architecture-and-scalability/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Implementing DllMain in a linux shared library</title>
		<link>http://tdistler.com/2007/10/05/implementing-dllmain-in-a-linux-shared-library</link>
		<comments>http://tdistler.com/2007/10/05/implementing-dllmain-in-a-linux-shared-library#comments</comments>
		<pubDate>Fri, 05 Oct 2007 18:00:43 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=40</guid>
		<description><![CDATA[Overview When writing a shared library, it is sometimes useful to have a set of functions that get called when the library is loaded and unloaded. In Windows, this is done by implementing the DllMain function. This function is called by the loader whenever a DLL is loaded or unloaded into the address space of [...]]]></description>
			<content:encoded><![CDATA[<h2>Overview</h2>
<p>When writing a shared library, it is sometimes useful to have a set of functions that get called when the library is loaded and unloaded. In Windows, this is done by implementing the DllMain function. This function is called by the loader whenever a DLL is loaded or unloaded into the address space of a process (and also when the process creates a new thread, but it is less common to handle this case). A value is passed in as an argument to the DllMain function that indicates which event is occurring: DLL load or unload.</p>
<p>On Linux, one must use the GCC __attribute__((constructor)) and __attribute__((destructor)) keywords (double underscores before and after) to explicitly declare functions to be called on load and unload. These keywords cause the compiler/linker to add the specified functions to the __CTOR_LIST__ and __DTOR_LIST__ (&#8220;ConstrucTOR LIST&#8221; and &#8220;DestrucTOR LIST&#8221; respectively) in the object file. Functions on the __CTOR_LIST__ are called by the loader when the library is loaded (either implicitly or by <strong>dlopen()</strong>). The main purpose for this list is to call the constructors on global objects in the library. Conversely, functions on the __DTOR_LIST__ are called when the library is unloaded (either implicitly or by <strong>dlclose()</strong>). By adding initialization and clean-up functions to this list, one can effectively replicate the DllMain functionality on Linux.</p>
<p><strong><em>NOTE: There are many ways to &#8220;shoot yourself in the foot&#8221; with these methods (on both Windows and Linux) because certain things aren&#8217;t available to your library until loading is complete. Don&#8217;t use these methods unless you have a real need&#8230; just export an Initialize() and Destroy() function instead, and force the consuming application to call them. Please read the &#8220;Gotcha&#8217;s&#8221; section below.</em></strong></p>
<p><span id="more-40"></span></p>
<h3>External Resources:</h3>
<ul>
<li><span class="nobr"><a rel="nofollow" href="http://msdn2.microsoft.com/en-us/library/ms682583.aspx" target="_blank">MSDN: DllMain</a></span></li>
<li><span class="nobr"><a rel="nofollow" href="http://www.dwheeler.com/program-library/Program-Library-HOWTO/miscellaneous.html" target="_blank">Misc. Linux Library Information</a></span></li>
<li><span class="nobr"><a rel="nofollow" href="http://linux4u.jinr.ru/usoft/WWW/www_debian.org/Documentation/elf/node11.html" target="_blank">Extended GCC Features</a></span></li>
<li><span class="nobr"><a rel="nofollow" href="http://www.securityfocus.com/infocus/1872" target="_blank">Dynamic Linking on Linux and Windows</a></span></li>
</ul>
<h2>Example: Linux</h2>
<div class="codeblock">
<p>void __attribute__ ((constructor)) my_load(void);<br />
void __attribute__ ((destructor))  my_unload(void);</p>
<p>// Called when the library is loaded and before dlopen() returns<br />
void my_load(void)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// Add initialization code&#8230;<br />
}</p>
<p>// Called when the library is unloaded and before dlclose()<br />
// returns<br />
void my_unload(void)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// Add clean-up code&#8230;<br />
}</p>
</div>
<h2>Example: Windows</h2>
<div class="codeblock">
<p>// Return TRUE on success and FALSE if an error occurs. Returning<br />
// FALSE will cause the library to be unloaded.<br />
BOOL WINAPI DllMain<br />
(<br />
&nbsp;&nbsp;&nbsp;&nbsp;HINSTANCE hinstDLL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;DWORD     fdwReason,<br />
&nbsp;&nbsp;&nbsp;&nbsp;LPVOID    lpReserved<br />
)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;switch (fdwReason)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;case DLL_PROCESS_ATTACH:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Add initialization code&#8230;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;case DLL_PROCESS_DETACH:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Add clean-up code&#8230;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;return (TRUE);<br />
}
</p></div>
<h2>Gotcha&#8217;s</h2>
<h3>Linux</h3>
<p><span class="nobr"><a rel="nofollow" href="http://www.dwheeler.com/program-library/Program-Library-HOWTO/miscellaneous.html" target="_blank">From www.dwheeler.com</a></span>:</p>
<blockquote><p>Shared libraries must not be compiled with the gcc arguments &#8220;-nostartfiles&#8221; or &#8220;-nostdlib&#8221;. If those arguments are used, the constructor/destructor routines will not be executed (unless special measures are taken).</p></blockquote>
<h3>Windows</h3>
<p><span class="nobr"><a rel="nofollow" href="http://msdn2.microsoft.com/en-us/library/ms682583.aspx" target="_blank">From Microsoft&#8217;s MSDN page on DllMain</a></span>:</p>
<blockquote><p>The entry-point function should perform only simple initialization or termination tasks. It must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these functions), because this may create dependency loops in the DLL load order. This can result in a DLL being used before the system has executed its initialization code. Similarly, the entry-point function must not call the FreeLibrary function (or a function that calls FreeLibrary) during process termination, because this can result in a DLL being used after the system has executed its termination code.</p>
<p>Because Kernel32.dll is guaranteed to be loaded in the process address space when the entry-point function is called, calling functions in Kernel32.dll does not result in the DLL being used before its initialization code has been executed. Therefore, the entry-point function can call functions in Kernel32.dll that do not load other DLLs. For example, DllMain can create synchronization objects such as critical sections and mutexes, and use TLS. Unfortunately, there is not a comprehensive list of safe functions in Kernel32.dll.</p>
<p>Windows 2000: Do not create a named synchronization object in DllMain because the system will then load an additional DLL. This restriction does not apply to subsequent versions of Windows.</p>
<p>Calling functions that require DLLs other than Kernel32.dll may result in problems that are difficult to diagnose. For example, calling User, Shell, and COM functions can cause access violation errors, because some functions load other system components. Conversely, calling functions such as these during termination can cause access violation errors because the corresponding component may already have been unloaded or uninitialized.</p>
<p>Because DLL notifications are serialized, entry-point functions should not attempt to communicate with other threads or processes. Deadlocks may occur as a result.</p>
<p>For information on best practices when writing a DLL, see <span class="nobr"><a rel="nofollow" href="http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx" target="_blank">http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx</a></span>.</p>
<p><span class="nobr">If your DLL is linked with the C run-time library (CRT), the entry point provided by the CRT calls the constructors and destructors for global and static C++ objects. Therefore, these restrictions for DllMain also apply to constructors and destructors and any code that is called from them.</span></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2007/10/05/implementing-dllmain-in-a-linux-shared-library/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

