<?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>schmichael&#039;s blog</title>
	<atom:link href="http://blog.schmichael.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.schmichael.com</link>
	<description>good good study, day day up</description>
	<lastBuildDate>Wed, 03 Oct 2012 07:27:55 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>MmStats in Scripts</title>
		<link>http://blog.schmichael.com/2012/10/03/mmstats-in-scripts/</link>
		<comments>http://blog.schmichael.com/2012/10/03/mmstats-in-scripts/#comments</comments>
		<pubDate>Wed, 03 Oct 2012 07:27:55 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[mmstats]]></category>

		<guid isPermaLink="false">http://blog.schmichael.com/?p=1031</guid>
		<description><![CDATA[MmStats is a library I created to expose and read statistics, metrics, and debugging information from running Python processes without the overhead of syscalls (eg writing to a socket or file) or threads, and to make sure that as many &#8230; <a href="http://blog.schmichael.com/2012/10/03/mmstats-in-scripts/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><a href="http://mmstats.readthedocs.org/">MmStats</a> is a library I created to expose and read statistics, metrics, and debugging information from running Python processes without the overhead of syscalls (eg writing to a socket or file) or threads, and to make sure that as many utilities as you want can read those metrics without affecting the performance of the main process exposing stats.</p>
<p>I <a href="http://pypi.python.org/pypi/mmstats/0.7.0">released 0.7</a> today to ease integration into multithreaded apps, but it made me realize a simpler tutorial would probably be helpful.</p>
<p>While I had web apps, job consumers, and other long running daemons in mind when I wrote mmstats, it turns out it&#8217;s also excellent for long running scripts.</p>
<p>You know the scripts: maintenance scripts, &#8220;fixer&#8221; scripts, slow build or deployment scripts, data migration scripts, etc.</p>
<p>If you&#8217;re like me, you always forget 2 things every time you write and run one of these scripts:</p>
<ol>
<li>Run it in <code>screen</code></li>
<li>Periodic progress output</li>
</ol>
<p>Luckily for #1 there&#8217;s already <a href="http://playingwithsid.blogspot.com/2007/10/disown-nohup-bash-commands.html">disown</a>.</p>
<p>For #2 we need an example script. Let&#8217;s pretend you have a Django app with users and you need to update their email addresses in a different system with something like this:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> otherdb
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">auth</span> <span style="color: #ff7700;font-weight:bold;">import</span> models
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #dc143c;">user</span> <span style="color: #ff7700;font-weight:bold;">in</span> models.<span style="color: black;">User</span>.<span style="color: black;">objects</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    otherdb.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">user</span>.<span style="color: black;">username</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">email</span><span style="color: #66cc66;">=</span><span style="color: #dc143c;">user</span>.<span style="color: #dc143c;">email</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>After forgetting to run it in screen, I&#8217;d restart it &#8230; and sit there &#8230; staring at my terminal &#8230; hating myself for not having it output anything.</p>
<p>But then these scripts never work the first time, so it&#8217;d probably die in flames on the first user without an email or similar exceptional condition I forgot to take into account.</p>
<p>So on my second attempt I&#8217;d probably quickly try to cobble together some progress indicator:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> otherdb
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">auth</span> <span style="color: #ff7700;font-weight:bold;">import</span> models
&nbsp;
BATCH <span style="color: #66cc66;">=</span> ...
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> i<span style="color: #66cc66;">,</span> <span style="color: #dc143c;">user</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>models.<span style="color: black;">User</span>.<span style="color: black;">objects</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> i % BATCH <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'{0} done'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Only update users who have emails! Otherwise otherdb dies.</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">user</span>.<span style="color: #dc143c;">email</span>:
        otherdb.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">user</span>.<span style="color: black;">username</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">email</span><span style="color: #66cc66;">=</span><span style="color: #dc143c;">user</span>.<span style="color: #dc143c;">email</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>But what should <code>BATCH</code> be? If I have 10,000 users, <code>BATCH = 1000</code> seems reasonable, but what if <code>otherdb</code> is <i>really</i> slow? In that case a smaller batch like 100 or 50 might be appropriate, so I don&#8217;t have to worry if <code>otherdb</code> just became unresponsive or something.</p>
<p>The best option is to <strong>always have your precise progress available at your request.</strong></p>
<h1>Using MmStats in Scripts</h1>
<p>I&#8217;ve found mmstats fits this use case beautifully. No more guessing at what might be an appropriate batch size or using the wrong format string in an uncommon case and crashing my script halfway through.</p>
<p>Integrating mmstats is as easy as:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
<span style="color: #ff7700;font-weight:bold;">import</span> mmstats
<span style="color: #ff7700;font-weight:bold;">import</span> otherdb
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">auth</span> <span style="color: #ff7700;font-weight:bold;">import</span> models
&nbsp;
<span style="color: #808080; font-style: italic;"># Define your stats in a model</span>
<span style="color: #ff7700;font-weight:bold;">class</span> S<span style="color: black;">&#40;</span>mmstats.<span style="color: black;">MmStats</span><span style="color: black;">&#41;</span>:
    done <span style="color: #66cc66;">=</span> mmstats.<span style="color: black;">CounterField</span><span style="color: black;">&#40;</span>label<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;done&quot;</span><span style="color: black;">&#41;</span>
    missing_email <span style="color: #66cc66;">=</span> mmstats.<span style="color: black;">CounterField</span><span style="color: black;">&#40;</span>label<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;missing_email&quot;</span><span style="color: black;">&#41;</span>
    otherdb_timer <span style="color: #66cc66;">=</span> mmstats.<span style="color: black;">TimerField</span><span style="color: black;">&#40;</span>label<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;otherdb_timer&quot;</span><span style="color: black;">&#41;</span>
    last_user <span style="color: #66cc66;">=</span> mmstats.<span style="color: black;">StringField</span><span style="color: black;">&#40;</span>label<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;user&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Instantiate the stats model</span>
stats <span style="color: #66cc66;">=</span> S<span style="color: black;">&#40;</span>filename<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;update-emails-{0}.mmstats&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> path<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;.&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> i<span style="color: #66cc66;">,</span> <span style="color: #dc143c;">user</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>models.<span style="color: black;">User</span>.<span style="color: black;">objects</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Update the username for readers to see</span>
    stats.<span style="color: black;">last_user</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">user</span>.<span style="color: black;">username</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Only update users who have emails! Otherwise otherdb dies.</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">user</span>.<span style="color: #dc143c;">email</span>:
        <span style="color: #ff7700;font-weight:bold;">with</span> stats.<span style="color: black;">otherdb_timer</span>:
            <span style="color: #808080; font-style: italic;"># Actually do the migration work</span>
            otherdb.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">user</span>.<span style="color: black;">username</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">email</span><span style="color: #66cc66;">=</span><span style="color: #dc143c;">user</span>.<span style="color: #dc143c;">email</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        stats.<span style="color: black;">missing_email</span>.<span style="color: black;">inc</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Increment the done counter to show another user has been processed</span>
    stats.<span style="color: black;">done</span>.<span style="color: black;">inc</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>That&#8217;s it! Now just re-run in screen, pop back into a shell and check on the progress with <code>slurpstats</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666;">schmichael@prod9000:~$ </span>slurpstats <span style="color: #000000; font-weight: bold;">*</span>.mmstats
==<span style="color: #000000; font-weight: bold;">&gt;</span> .<span style="color: #000000; font-weight: bold;">/</span>update-emails-<span style="color: #000000;">1234567890</span>.mmstats
  <span style="color: #000000; font-weight: bold;">done</span>               <span style="color: #000000;">113</span>
  missing_email      <span style="color: #000000;">12</span>
  otherdb_timer      <span style="color: #000000;">0.3601293582</span>
  user               rob
  sys.created        <span style="color: #000000;">1346884490.7</span>
  sys.pid            <span style="color: #000000;">10298</span>
  sys.gid            <span style="color: #000000;">549</span>
  ...</pre></td></tr></table></div>

<p>This output would indicate 113 users have been checked, 12 of them had no email, &#8220;rob&#8221; is the current user being processed, and that <code>otherdb.update(...)</code> takes on average 360ms to complete. <small>By default timers average the last 100 values, but that&#8217;s customizable via the size keyword argument.</small></p>
<p>That&#8217;s nice and all, but it&#8217;d be more fun to see <strong>how many users were updated per second.</strong> <code>pollstats</code> is a simple tool for doing just that:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666;">schmichael@prod9000:~$ </span>pollstats <span style="color: #000000; font-weight: bold;">done</span>,missing_email <span style="color: #000000; font-weight: bold;">*</span>.mmstats
       <span style="color: #000000; font-weight: bold;">done</span>         <span style="color: #000000; font-weight: bold;">|</span>      missing_email
                <span style="color: #000000;">213</span> <span style="color: #000000; font-weight: bold;">|</span>                 <span style="color: #000000;">20</span>
                  <span style="color: #000000;">3</span> <span style="color: #000000; font-weight: bold;">|</span>                  <span style="color: #000000;">0</span>
                  <span style="color: #000000;">5</span> <span style="color: #000000; font-weight: bold;">|</span>                  <span style="color: #000000;">1</span>
                  <span style="color: #000000;">1</span> <span style="color: #000000; font-weight: bold;">|</span>                  <span style="color: #000000;">0</span>
...</pre></td></tr></table></div>

<p><code>pollstats</code> will print out the current value of the given counters initially, and then once per second print the delta. So in our contrived example we&#8217;d be processing somewhere between 1 and 5 users per second and less than 1 missing email per second.</p>
<p>Sadly <code>pollstats</code> is extremely simplistic at the moment and lacks the ability to intelligently display non-counter fields. (Patches welcome!)</p>
<p>Even better: if you&#8217;re script dies the mmstats file will be left for you to inspect. (Although if you want it perfectly in sync you should probably <code>stats.flush()</code> on each iteration.)</p>
<p>mmstats is still young (pre-1.0 for a reason) and simplistic, but I already find it extremely useful not only in web apps and other daemons, but also in simple &#8211; or not so simple &#8211; one-off scripts. I hope you find it useful as well!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2012/10/03/mmstats-in-scripts/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Building Python 2.6.8 on Ubuntu 12.04</title>
		<link>http://blog.schmichael.com/2012/05/29/building-python-2-6-8-on-ubuntu-12-04/</link>
		<comments>http://blog.schmichael.com/2012/05/29/building-python-2-6-8-on-ubuntu-12-04/#comments</comments>
		<pubDate>Tue, 29 May 2012 22:17:15 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.schmichael.com/?p=996</guid>
		<description><![CDATA[Update 2012-06-01: Looks like pythonz is an easier way to install Python 2.6.8 (and all other Pythons) on Ubuntu 12.04. Ubuntu 12.04 builds OpenSSL without SSLv2. Python 2.6.8 expects OpenSSL to be built with SSLv2. This is a bug that &#8230; <a href="http://blog.schmichael.com/2012/05/29/building-python-2-6-8-on-ubuntu-12-04/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><strong>Update 2012-06-01:</strong> Looks like <a href="https://github.com/saghul/pythonz">pythonz</a> is an easier way to install Python 2.6.8 (and all other Pythons) on Ubuntu 12.04.</p>
<p>Ubuntu 12.04 builds OpenSSL without SSLv2. Python 2.6.8 expects OpenSSL to be built with SSLv2.</p>
<p><a href="http://bugs.python.org/issue12012">This is a bug that has been fixed in Python 2.7+</a>, but it wasn&#8217;t backported for Python 2.6.</p>
<p>So if you build your own Python 2.6 binaries on Ubuntu 12.04 you&#8217;ll see errors like this when attempting to use anything SSL related:</p>
<p><code>*** WARNING: renaming "_ssl" since importing it failed: build/lib.linux-x86_64-2.6/_ssl.so: undefined symbol: SSLv2_method</code></p>
<p>Some of us still need Python 2.6, so <a href="https://bitbucket.org/schmichael/cpython-v2.6.8-nosslv2/src/d77684a8fdd5">I forked Python 2.6.8 and removed SSLv2 support</a>. Tests pass and SSL works.</p>
<p>You can also just grab the diff below:</p>
<p><script src="https://gist.github.com/2831049.js"> </script></p>
<p><strong>Update:</strong> M2Crypto requires patching as well: <script src="https://gist.github.com/2831510.js"> </script></p>
<p><strong>Update 2:</strong> If you trust me and use 64bit Ubuntu 12.04 you can download a pre-built <a href="http://schmichael.com/files/python-2.6.8~nosslv2.tar.gz">python-2.6.8~nosslv2</a> tarball from me. Includes distribute and pip pre-installed.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2012/05/29/building-python-2-6-8-on-ubuntu-12-04/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Failing with MongoDB</title>
		<link>http://blog.schmichael.com/2011/11/05/failing-with-mongodb/</link>
		<comments>http://blog.schmichael.com/2011/11/05/failing-with-mongodb/#comments</comments>
		<pubDate>Sat, 05 Nov 2011 19:06:03 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[mongodb]]></category>

		<guid isPermaLink="false">http://blog.schmichael.com/?p=979</guid>
		<description><![CDATA[Update: Sorry this isn&#8217;t my best piece of writing and there seems to be some confusion. The dataset in question was first in a 1.8 master/slave pair and then migrated to sharded replica sets and 2.0.0. For a bit of &#8230; <a href="http://blog.schmichael.com/2011/11/05/failing-with-mongodb/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><b>Update:</b> Sorry this isn&#8217;t my best piece of writing and there seems to be some confusion. The dataset in question was first in a 1.8 master/slave pair and then migrated to sharded replica sets and 2.0.0.</p>
<p>For a bit of history of my dealings with MongoDB at Urban Airship, I gave a couple versions of a Scaling with MongoDB talk:</p>
<ul>
<li>
<a href="http://opensourcebridge.org/2011/wiki/Scaling_with_MongoDB">at Open Source Bridge (latest &#038; greatest)</a>
</li>
<li><a href="/2011/02/02/schmongodb-slides-from-update-portland/">at Update Portland (original, less polished version)</a></li>
</ul>
<p>My coworker Adam Lowry even gave a follow-up talk of sorts at <a href="http://postgresopen.org/2011/schedule/presentations/98/">Postgres Open 2011</a> (<a href="http://wiki.postgresql.org/images/7/7f/Adam-lowry-postgresopen2011.pdf">slides</a>) about migrating one of our datasets off of MongoDB and (back) on to PostgreSQL.</p>
<p>After reading through those slides you&#8217;re probably wondering why we&#8217;re still dealing with MongoDB at all. We fully intended to migrate our data out of it by now, but priorities change, deadlines slip, and we never expected one of our last uses of MongoDB to experience a surge in growth.</p>
<p>The dataset in question seemed ideal for MongoDB:</p>
<ul>
<li>Ephemeral &#8211; if we lose it we experience service degradation for a short while, but nothing catastrophic</li>
<li>Small &#8211; easily fits into memory (~15 GB)</li>
<li>Secondary index &#8211; In a key/value store we would have had to manage a secondary index manually</li>
</ul>
<p>So this dataset dodged a lot of the previous problems we had with MongoDB and seemed safe to migrate at our leisure.</p>
<p><a name="global_write_lock"><b>Global Write Lock</b></a></p>
<p><a href="http://www.mongodb.org/display/DOCS/How+does+concurrency+work#Howdoesconcurrencywork-Read%2FWriteLock">MongoDB has a global write lock.</a> This means that while applying an insert or update, a single mongod instance can&#8217;t respond to other queries.</p>
<p>Our dataset may be small but it has a heavy read and write load. When the service it backed experienced a surge in usage, MongoDB quickly became CPU bound. This was especially frustrating considering mongod was running in a simple master/slave setup on two servers: each with 16 cores and enough memory to hold all the data a few times over again.</p>
<p>Because of the global write lock and heavy write load, operations are effectively serialized and executed on a single core. Meaning our servers didn&#8217;t even look loaded, as just 1 core would be 100% utilized by mongod.</p>
<p><a name="sharding"><b>Let the Sharding Begin</b></a></p>
<p>So we need to utilize multiple cores&#8230;<br />
To do that we need multiple write locks&#8230;<br />
There&#8217;s 1 write lock per mongod. So&#8230;<br />
&#8230;multiple mongods per server?</p>
<p>We&#8217;d been avoiding sharding after having no luck getting it working in the 1.5.x dev series, but it&#8217;s our only choice now to get multiple mongods. I ran some tests and it seemed like we could turn our master/slave setup into a 2 shard setup with 2 mongods and 1 arbiter per shard with downtime in the seconds or low minutes.</p>
<p>The operational complexity of configuring a MongoDB cluster is daunting with each component bringing its own caveats:</p>
<p><b>mongod config servers</b></p>
<ul>
<li>You need <i>exactly</i> 3 config mongods (1 is fine for testing, which makes things appear simpler than they really are).</li>
<li>There are lots of caveats with the config servers, so read <a href="http://www.mongodb.org/display/DOCS/Changing+Config+Servers">Changing Config Servers</a> carefully before configuring your cluster.</li>
<li>Otherwise these mongod instances are fairly blackboxish to me. Despite being mongod processes you administer them completely differently.</li>
</ul>
<p><b>mongos routers</b></p>
<ul>
<li>1 per app server. This wouldn&#8217;t be a big deal <a href="http://www.mongodb.org/display/DOCS/flushRouterConfig+command">except that our mongoses often start failing and require flushRouterConfig to be run on them</a>. <a href="https://jira.mongodb.org/browse/SERVER-3739">2.0.1 supposedly fixes this</a>, but we haven&#8217;t tested that yet (and trading known problems for new unknown ones is always scary).</li>
<li>mongos instances can use a lot of CPU and seem to have random spikes where they fully utilize every core very briefly. Keep this in mind if your application servers are already CPU bound.</li>
<li>On the bright side mongos balanced our data rather quickly. Our shard key is a uuid, and it properly setup reasonable ranges in very short order without having to preconfigure them.</li>
<li>&#8220;mongos&#8221; is a terribly confusing name. It sounds like multiple mongo instances. We&#8217;ve taken to calling them mongooses internally due to frequent typos and confusion.</li>
</ul>
<p><b>arbiters</b></p>
<ul>
<li>You need at least 3 members in a replica set in order to complete an election if 1 member goes down.</li>
<li>We haven&#8217;t had any issues with arbiters&#8230; not sure what we&#8217;d do if one broke somehow but since they have no persistent data they&#8217;re safe to restart at any time.</li>
</ul>
<p><b>mongods</b></p>
<ul>
<li>Early on we ran into a problem where changing replica set member entries wasn&#8217;t propagated to the config servers&#8217; shard configuration. Restarting every mongos fixed it.</li>
<li>As far as I can tell a new replica set member will never leave the initial RECOVERING state until all operations to that set are stopped. Even 40 updates per second was enough of a trickle to prevent a new set member from leaving RECOVERING to becoming a SECONDARY. We had to shutdown mongoses to cut off all traffic to bring up a new member. (The replication log gave every indication of being caught up and our usual update load is thousands per second.)</li>
<li>Setting rest in the config file doesn&#8217;t seem to work. Put &#8211;rest in your command line options.</li>
<li>Sending an HTTP request to a mongod&#8217;s main port (instead of the HTTP endpoint) seems to be capable of crashing the mongod.</li>
</ul>
<p><b>Client Drivers</b></p>
<p>While a single replica set member was in a RECOVERING state our Java services couldn&#8217;t complete <i>any</i> operations while our Python service was happily working away.</p>
<p><b>Summary</b></p>
<p>Right now we&#8217;re getting by with 2 shards on 2 dedicated servers and then mongoses and config servers spread throughout other servers. There appears to be some data loss occurring, though due to the ephemeral fast changing nature of this dataset it&#8217;s very difficult to determine definitively or reproduce independently.</p>
<p>So we&#8217;re trying to migrate off of MongoDB to a custom service better suited for this dataset ASAP.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2011/11/05/failing-with-mongodb/feed/</wfw:commentRss>
		<slash:comments>48</slash:comments>
		</item>
		<item>
		<title>MemoryMapFile Convenience Class for Python</title>
		<link>http://blog.schmichael.com/2011/09/05/memorymapfile-convenience-class-for-python/</link>
		<comments>http://blog.schmichael.com/2011/09/05/memorymapfile-convenience-class-for-python/#comments</comments>
		<pubDate>Tue, 06 Sep 2011 05:54:25 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[mmap]]></category>

		<guid isPermaLink="false">http://blog.schmichael.com/?p=968</guid>
		<description><![CDATA[My obsession with mmap hasn&#8217;t died, but while Python&#8217;s mmap module is a wonderful low level library it&#8217;s a bit hard for a newcomer to use properly. I&#8217;ve started toying with a convenience wrapper class for mmap.mmap (at least the &#8230; <a href="http://blog.schmichael.com/2011/09/05/memorymapfile-convenience-class-for-python/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>My <a href="/2011/05/15/sharing-python-data-between-processes-using-mmap/">obsession</a> with <a href="http://en.wikipedia.org/wiki/Mmap">mmap</a> hasn&#8217;t died, but while <a href="http://docs.python.org/library/mmap">Python&#8217;s mmap module</a> is a wonderful low level library it&#8217;s a bit hard for a newcomer to use properly.</p>
<p>I&#8217;ve started toying with a convenience wrapper class for <code>mmap.mmap</code> (at least the Unix version):<br />
<script src="https://gist.github.com/1196686.js?file=memorymap.py"></script></p>
<p>My original goal was to automatically <a href="http://docs.python.org/library/mmap#mmap.resize">grow</a> the mmap whenever the user attempts to write beyond the current size of the mmap file, but that&#8217;s going to take carefully wrapping quite a few methods (<code>write</code>, <code>__setitem__</code>, and maybe get/read methods too).</p>
<p>If it becomes useful, I may use it in <a href="https://github.com/schmichael/mmstats">mmstats</a>.</p>
<p>Feedback welcome!</p>
<p><strong>Update:</strong> Discovered the hard way (segfaults) that resizing mmaps is tricky: the region can be moved but data will be copied. However, any existing pointers (from ctypes.<type>.from_buffer in my case) will now point to freed memory and segfault upon use.</p>
<p>tl;dr &#8211; If at all possible, precompute the size of your mmap before using it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2011/09/05/memorymapfile-convenience-class-for-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sharing Python data between processes using mmap</title>
		<link>http://blog.schmichael.com/2011/05/15/sharing-python-data-between-processes-using-mmap/</link>
		<comments>http://blog.schmichael.com/2011/05/15/sharing-python-data-between-processes-using-mmap/#comments</comments>
		<pubDate>Mon, 16 May 2011 04:28:29 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[ctypes]]></category>
		<category><![CDATA[mmap]]></category>
		<category><![CDATA[struct]]></category>

		<guid isPermaLink="false">http://blog.schmichael.com/?p=947</guid>
		<description><![CDATA[I&#8217;ve been toying with an idea of exposing statistics for a Python application via shared memory to keep the performance impact on the application as low as possible. The goal being an application could passively expose a number of metrics &#8230; <a href="http://blog.schmichael.com/2011/05/15/sharing-python-data-between-processes-using-mmap/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been toying with an idea of exposing statistics for a Python application via shared memory to keep the performance impact on the application as low as possible. The goal being an application could passively expose a number of metrics that could either be periodically polled via <a href="http://munin-monitoring.org/">munin</a>/<a href="http://www.icinga.org/">Icinga</a>/etc plugins or interactive tools when diagnosing issues on a system.</p>
<p>But first things first: I need to put data into <a href="http://en.wikipedia.org/wiki/Shared_memory">shared memory</a> from Python. <a href="http://en.wikipedia.org/wiki/Mmap">mmap</a> is an excellent widely-implemented POSIX system call for creating a shared memory space backed by an on-disk file.</p>
<p>Usually in the UNIX world you have 2 ways of accessing/manipulating data: memory addresses or streams (files). Manipulating data via memory addresses means <a href="http://en.wikipedia.org/wiki/Pointer_%28computing%29">pointers</a>, offsets, <a href="http://en.wikipedia.org/wiki/Malloc">malloc/free</a>, etc. Stream interfaces manipulate data via <a href="http://en.wikipedia.org/wiki/System_call">read/write/seek system calls</a> for files and <a href="http://en.wikipedia.org/wiki/Berkeley_sockets">send/recv/etc for sockets</a>.</p>
<p>mmap gives you both interfaces. A memory mapped file can be manipulated via read/write/seek or by directly accessing its mapped memory region. The advantage of the latter is that this memory region is in userspace &#8212; meaning you can manipulate a file without incurring the overhead of write system calls for every manipulation.</p>
<p>Anyway, enough exposition, let&#8217;s see some code. <small>(Despite mmap&#8217;s nice featureset, I&#8217;m only using it as a simple memory sharing mechanism anyway.)</small> The following code shares a tiny bit of data between 2 Python processes using the excellent <a href="http://docs.python.org/library/mmap">mmap module in the stdlib</a>. <code>a.py</code> writes to the memory mapped region, and <code>b.py</code> reads the data out. <a href="http://docs.python.org/library/ctypes">ctypes</a> allows for an easy way to create values in a memory mapped region and manipulate them like &#8220;normal&#8221; Python objects.</p>
<p><em>These code samples were written using Python 2.7 on Linux. They should work fine on any POSIX system, but Windows users will have to change the mmap calls to match the Windows API.</em></p>
<p><strong>a.py</strong></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #ff7700;font-weight:bold;">import</span> ctypes
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">mmap</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">struct</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Create new empty file to back memory map on disk</span>
    fd <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">os</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/mmaptest'</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">O_CREAT</span> | <span style="color: #dc143c;">os</span>.<span style="color: black;">O_TRUNC</span> | <span style="color: #dc143c;">os</span>.<span style="color: black;">O_RDWR</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Zero out the file to insure it's the right size</span>
    <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span>fd<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>00'</span> * <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PAGESIZE</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PAGESIZE</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Create the mmap instace with the following params:</span>
    <span style="color: #808080; font-style: italic;"># fd: File descriptor which backs the mapping or -1 for anonymous mapping</span>
    <span style="color: #808080; font-style: italic;"># length: Must in multiples of PAGESIZE (usually 4 KB)</span>
    <span style="color: #808080; font-style: italic;"># flags: MAP_SHARED means other processes can share this mmap</span>
    <span style="color: #808080; font-style: italic;"># prot: PROT_WRITE means this process can write to this mmap</span>
    buf <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">mmap</span>.<span style="color: #dc143c;">mmap</span><span style="color: black;">&#40;</span>fd<span style="color: #66cc66;">,</span> <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PAGESIZE</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">mmap</span>.<span style="color: black;">MAP_SHARED</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PROT_WRITE</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Now create an int in the memory mapping</span>
    i <span style="color: #66cc66;">=</span> ctypes.<span style="color: black;">c_int</span>.<span style="color: black;">from_buffer</span><span style="color: black;">&#40;</span>buf<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Set a value</span>
    i.<span style="color: black;">value</span> <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">10</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># And manipulate it for kicks</span>
    i.<span style="color: black;">value</span> +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">assert</span> i.<span style="color: black;">value</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">11</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Before we create a new value, we need to find the offset of the next free</span>
    <span style="color: #808080; font-style: italic;"># memory address within the mmap</span>
    offset <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">struct</span>.<span style="color: black;">calcsize</span><span style="color: black;">&#40;</span>i._type_<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># The offset should be uninitialized ('\x00')</span>
    <span style="color: #ff7700;font-weight:bold;">assert</span> buf<span style="color: black;">&#91;</span>offset<span style="color: black;">&#93;</span> <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>00'</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Now ceate a string containing 'foo' by first creating a c_char array</span>
    s_type <span style="color: #66cc66;">=</span> ctypes.<span style="color: black;">c_char</span> * <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'foo'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Now create the ctypes instance</span>
    s <span style="color: #66cc66;">=</span> s_type.<span style="color: black;">from_buffer</span><span style="color: black;">&#40;</span>buf<span style="color: #66cc66;">,</span> offset<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># And finally set it</span>
    s.<span style="color: black;">raw</span> <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'foo'</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'First 10 bytes of memory mapping: %r'</span> % buf<span style="color: black;">&#91;</span>:<span style="color: #ff4500;">10</span><span style="color: black;">&#93;</span>
    <span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Now run b.py and press ENTER'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Changing i'</span>
    i.<span style="color: black;">value</span> *<span style="color: #66cc66;">=</span> i.<span style="color: black;">value</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Changing s'</span>
    s.<span style="color: black;">raw</span> <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'bar'</span>
&nbsp;
    new_i <span style="color: #66cc66;">=</span> <span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Enter a new value for i: '</span><span style="color: black;">&#41;</span>
    i.<span style="color: black;">value</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>new_i<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><strong>b.py</strong></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">mmap</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">struct</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Open the file for reading</span>
    fd <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">os</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/mmaptest'</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">O_RDONLY</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Memory map the file</span>
    buf <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">mmap</span>.<span style="color: #dc143c;">mmap</span><span style="color: black;">&#40;</span>fd<span style="color: #66cc66;">,</span> <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PAGESIZE</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">mmap</span>.<span style="color: black;">MAP_SHARED</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">mmap</span>.<span style="color: black;">PROT_READ</span><span style="color: black;">&#41;</span>
&nbsp;
    i <span style="color: #66cc66;">=</span> <span style="color: #008000;">None</span>
    s <span style="color: #66cc66;">=</span> <span style="color: #008000;">None</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
        new_i<span style="color: #66cc66;">,</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">struct</span>.<span style="color: black;">unpack</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'i'</span><span style="color: #66cc66;">,</span> buf<span style="color: black;">&#91;</span>:<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        new_s<span style="color: #66cc66;">,</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">struct</span>.<span style="color: black;">unpack</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'3s'</span><span style="color: #66cc66;">,</span> buf<span style="color: black;">&#91;</span><span style="color: #ff4500;">4</span>:<span style="color: #ff4500;">7</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> i <span style="color: #66cc66;">!=</span> new_i <span style="color: #ff7700;font-weight:bold;">or</span> s <span style="color: #66cc66;">!=</span> new_s:
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'i: %s =&gt; %d'</span> % <span style="color: black;">&#40;</span>i<span style="color: #66cc66;">,</span> new_i<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'s: %s =&gt; %s'</span> % <span style="color: black;">&#40;</span>s<span style="color: #66cc66;">,</span> new_s<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Press Ctrl-C to exit'</span>
            i <span style="color: #66cc66;">=</span> new_i
            s <span style="color: #66cc66;">=</span> new_s
&nbsp;
        <span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><small>(Note that I cruelly don&#8217;t clean up /tmp/mmaptest after the scripts finished. Consider it a 4KB tax for anyone who runs arbitrary code they found on the Internet without reading it first.)</small></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2011/05/15/sharing-python-data-between-processes-using-mmap/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>signalfd</title>
		<link>http://blog.schmichael.com/2011/02/20/signalfd/</link>
		<comments>http://blog.schmichael.com/2011/02/20/signalfd/#comments</comments>
		<pubDate>Mon, 21 Feb 2011 06:50:07 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.schmichael.com/?p=920</guid>
		<description><![CDATA[This article covers signalfd, a system call only available on Linux. If anyone knows of an equivalent for OSX or BSDs,* please let me know. It&#8217;d be great to create a compatibility layer. Writing asynchronous IO code is fun; handling &#8230; <a href="http://blog.schmichael.com/2011/02/20/signalfd/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><em>This article covers </em>signalfd<em>, a system call only available on Linux. If anyone knows of an equivalent for OSX or BSDs,<abbrev title="If there's something like signalfd for Windows, I'm sorry but I really couldn't care less.">*</abbrev> please <a href="/about-me/">let me know</a>. It&#8217;d be great to create a compatibility layer.</em></p>
<p>Writing asynchronous IO code is fun; handling signals is not. <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/signalfd.2.html">signalfd</a> allows you to move your signal handling code into your main event loop instead of hooking up global handlers and using the featureless <a href="http://docs.python.org/library/signal#signal.set_wakeup_fd">set_wakeup_fd</a> function to break the main loop.</p>
<p>Luckily <a href="https://launchpad.net/python-signalfd">Jean-Paul Calderone had already created a great Python wrapper for the signalfd and sigprocmask system calls</a>. Unfortunately it doesn&#8217;t include a way to parse the siginfo_t structure which contains all the useful information about the signal you&#8217;re handling.</p>
<p>I&#8217;ve added a helper to do just that in a branch:</p>
<p><a href="https://code.launchpad.net/~schmichael/python-signalfd/helpers">https://code.launchpad.net/~schmichael/python-signalfd/helpers</a></p>
<p>A sample program would look like:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">select</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">signal</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> signalfd
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> sigfdtest<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Catch them all!</span>
    sigs <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> attr <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">signal</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> attr.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'SIG'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> attr.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'SIG_'</span><span style="color: black;">&#41;</span>:
            sigs.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">signal</span><span style="color: #66cc66;">,</span> attr<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    sfd <span style="color: #66cc66;">=</span> signalfd.<span style="color: black;">create_signalfd</span><span style="color: black;">&#40;</span>sigs<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Capturing: %r'</span> % <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span>sigs<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'selecting - pid: %d'</span> % <span style="color: #dc143c;">os</span>.<span style="color: black;">getpid</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        r <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">select</span>.<span style="color: #dc143c;">select</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>sfd<span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> s <span style="color: #ff7700;font-weight:bold;">in</span> r:
            <span style="color: #ff7700;font-weight:bold;">assert</span> s <span style="color: #ff7700;font-weight:bold;">is</span> sfd<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Python nicely re-uses the fd instance'</span>
            sig <span style="color: #66cc66;">=</span> signalfd.<span style="color: black;">read_signalfd</span><span style="color: black;">&#40;</span>sfd<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> sig
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
    sigfdtest<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>When run you can throw some signals at it:</p>
<pre>
Capturing: [6, 14, 7, 17, 17, 18, 8, 1, 4, 2, 29, 6, 9, 13, 29, 27, 30, 3, 64, 34, 11, 19, 31, 15, 5, 20, 21, 22, 23, 10, 12, 26, 28, 24, 25]
selecting - pid: 6523
^CSIGINT
selecting - pid: 6523
^CSIGINT
selecting - pid: 6523
SIGHUP
selecting - pid: 6523
Killed
</pre>
<p>Of course you&#8217;ll need to use an uninterpretable signal like KILL to exit.</p>
<p><a href="http://bugs.python.org/issue8407">Jean-Paul attempted to get signalfd included in Python 2.7&#8242;s signal module, and it was slated for inclusion in 3.2</a>. However, given that <a href="http://www.python.org/download/releases/3.2/">3.2</a> was just <a href="http://docs.python.org/release/3.2/library/signal">released without it</a>, I&#8217;m guessing the attempt to get this functionality into Python&#8217;s stdlib has been forgotten.</p>
<p>Up next: <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/eventfd.2.html">eventfd</a> perhaps?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2011/02/20/signalfd/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
