<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xml:lang="ja">
	<channel>
		<title>はてなるせだいあり</title>
		<link>http://d.hatena.ne.jp/nurse/</link>
		<description>はてなるせだいあり</description>
		<dc:creator>nurse</dc:creator>


		<item>
			<title>[%ruby]観察日記 2010-02-09</title>
			<link>http://d.hatena.ne.jp/nurse/20100209#1265673814</link>

			<description><![CDATA[
		<div class="section">
			<p>NetBSDにかまけていてサボっていましたが、まぁぼちぼち。</p>
			<h4>make clean</h4>
			<blockquote>
			<p>(mame) make clean してもえらいいろいろ残るな</p>
			<p>(mame) parse.c とか prelude.c とか</p>
			<p>(eban) parse.cはtarballでいしょに配布してるので消すわけにはいかない</p>
			<p>(mame) tarball のパッケージではどのみち make clean 使うなってスタンスではなかったっけ</p>
			<p>(mame) 見つからないから気のせいか (注: 以前 IRC でそのような話がでていた)</p>
			<p>(mrkn) そもそも make clean は中途半端で、</p>
			<p>(mrkn) ビルドを途中で止めてmake clean したりすると enc 以下の clean でエラーでたりする</p>
			<p>(eban) 昔はmake cleanがminirubyに依存してたりしたので、そのあたりの名残りで不整合があるんだろうな</p>
			</blockquote>
			<h4>M17N の教訓</h4>
			<blockquote>
			<p>(mame) Ruby の M17N 化を通して得られた経験は</p>
			<p>(mame) 論文にまとめておくと未来の為になる気がする</p>
			<p>(mame) まあ、CSI 方式は難しいから避けよう、という教訓にしかならないかもしれない</p>
			<p>(kosaki) スクリプト言語だと、文字列以外も stringでやる伝統があるのでCSIと相性が悪くて云々というスジ</p>
			<p>で</p>
			</blockquote>
			<p>Perl は UCS 正規化方式だけれど、やっぱり文字列とバイト列絡みでは色々踏んだ記憶がある。</p>
			<h4>BigDecimal</h4>
			<p>あらすじ――RubySpec 修正に燃える mame、しかし、BigDecimal という強大な敵が立ちはだかるのであった― ―</p>
			<blockquote>
			<p>(mame) BigDecimal のターゲットユーザってどんなんだろう</p>
			</blockquote>
			<p>経理とか金融とか Rails とか諸説ありますが、実際の所どうなんでしょうね。</p>
			<p>なお、BigDecimalシリーズはしばらく続きます</p>
		</div>
]]></description>

			<dc:creator>nurse</dc:creator>

			<pubDate>Tue, 09 Feb 2010 00:03:34 GMT</pubDate>



			<category>%ruby</category>


		</item>

		<item>
			<title>NetBSD 5.0 における pthread と fork</title>
			<link>http://d.hatena.ne.jp/nurse/20100207#1265544753</link>

			<description><![CDATA[
		<div class="section">
			<h4>概要</h4>
			<p>NetBSD 5.0 において、複数の pthread が生きている状態で fork するとおかしくなる。</p>
			<h4>再現</h4>
			<p><a href="http://nalsh.jp/patches/atfork.c" target="_blank">再現プログラム</a>ではfork前に一度3つのpthreadを作り、その後1つ殺して lwpid 1 と 3 が残っている。この状態で3からforkすると子では3が残り、これにlwpid 1が割り当てられるのだが、どこかに3の情報が残っていて、その後呼びに行ってしまう</p>
			<blockquote>
			<p> 22612      2 a.out    CALL  _lwp_park(0xbb7ffd94,3,0x8049198,0x8049198)</p>
			<p> 22612      2 a.out    RET   _lwp_park -1 errno 3 No such process</p>
			</blockquote>
			<h4>詳細</h4>
			<p>NetBSD 5.0 ではカーネルスレッドに当たる lwp (light weight process) とユーザレベルを司る pthread が 1:1　対応している。プロセス内に存在する lwp の情報は、以下のあたりに保存されている。</p>
<pre class="syntax-highlight">
<span class="synComment">// /usr/include/sys/lwp.h</span>
<span class="synType">struct</span> lwp {
        ...
        <span class="synComment">/* Process level and global state, misc. */</span>
        LIST_ENTRY(lwp) l_list;         <span class="synComment">/* a: entry on list of all LWPs */</span>
        <span class="synType">void</span>            *l_ctxlink;     <span class="synComment">/* p: uc_link {get,set}context */</span>
        <span class="synType">struct</span> proc     *l_proc;        <span class="synComment">/* p: parent process */</span>
        LIST_ENTRY(lwp) l_sibling;      <span class="synComment">/* p: entry on proc's list of LWPs */</span>
        ...
};
</pre>

<pre class="syntax-highlight">
<span class="synComment">// /usr/include/sys/lwp.h</span>
<span class="synType">struct</span> proc {
        ...
        pid_t           p_pid;          <span class="synComment">/* :: Process identifier. */</span>
        LIST_ENTRY(proc) p_pglist;      <span class="synComment">/* l: List of processes in pgrp. */</span>
        <span class="synType">struct</span> proc     *p_pptr;        <span class="synComment">/* l: Pointer to parent process. */</span>
        LIST_ENTRY(proc) p_sibling;     <span class="synComment">/* l: List of sibling processes. */</span>
        LIST_HEAD(, proc) p_children;   <span class="synComment">/* l: List of children. */</span>
        LIST_HEAD(, lwp) p_lwps;        <span class="synComment">/* p: List of LWPs. */</span>
        <span class="synType">struct</span> ras      *p_raslist;     <span class="synComment">/* a: List of RAS entries */</span>

<span class="synComment">/* The following fields are all zeroed upon creation in fork. */</span>
<span class="synPreProc">#define p_startzero     p_nlwps</span>

        <span class="synType">int</span>             p_nlwps;        <span class="synComment">/* p: Number of LWPs */</span>
        <span class="synType">int</span>             p_nzlwps;       <span class="synComment">/* p: Number of zombie LWPs */</span>
        <span class="synType">int</span>             p_nrlwps;       <span class="synComment">/* p: Number running/sleeping LWPs */</span>
        <span class="synType">int</span>             p_nlwpwait;     <span class="synComment">/* p: Number of LWPs in lwp_wait1() */</span>
        <span class="synType">int</span>             p_ndlwps;       <span class="synComment">/* p: Number of detached LWPs */</span>
        <span class="synType">int</span>             p_nlwpid;       <span class="synComment">/* p: Next LWP ID */</span>
        ...
};
</pre>

			<p>fork は実際には /sys/kern/kern_fork.c の fork1 で行われていて、ここでプロセスの複製と initial thread の作成を行っている模様。initial thread は fork を実行した lwp をテンプレートにして作られる。</p>
<pre class="syntax-highlight">
        <span class="synComment">/*</span>
<span class="synComment">         * Finish creating the child process.</span>
<span class="synComment">         * It will return through a different path later.</span>
<span class="synComment">         */</span>
        lwp_create(l1, p2, uaddr, inmem, (flags &#38; FORK_PPWAIT) ? LWP_VFORK : <span class="synConstant">0</span>,
            stack, stacksize, (func != <span class="synConstant">NULL</span>) ? func : child_return, arg, &#38;l2,
            l1-&#62;l_class);

        <span class="synComment">/*</span>
<span class="synComment">         * It's now safe for the scheduler and other processes to see the</span>
<span class="synComment">         * child process.</span>
<span class="synComment">         */</span>
        mutex_enter(proc_lock);

        <span class="synStatement">if</span> (p1-&#62;p_session-&#62;s_ttyvp != <span class="synConstant">NULL</span> &#38;&#38; p1-&#62;p_lflag &#38; PL_CONTROLT)
                p2-&#62;p_lflag |= PL_CONTROLT;

        LIST_INSERT_HEAD(&#38;parent-&#62;p_children, p2, p_sibling);
        p2-&#62;p_exitsig = exitsig;                <span class="synComment">/* signal for parent on exit */</span>

        LIST_INSERT_AFTER(p1, p2, p_pglist);
        LIST_INSERT_HEAD(&#38;allproc, p2, p_list);
</pre>

			<p>この lwp_create は /usr/src/sys/kern/kern_lwp.c にある。しかし、引用部の後半にある、プロセスの lwp リストに新しい lwp を追加するコードは、別のプロセスの lwp をテンプレートにした場合を考慮しているように見えない。</p>
<pre class="syntax-highlight">
<span class="synComment">/*</span>
<span class="synComment"> * Create a new LWP within process 'p2', using LWP 'l1' as a template.</span>
<span class="synComment"> * The new LWP is created in state LSIDL and must be set running,</span>
<span class="synComment"> * suspended, or stopped by the caller.</span>
<span class="synComment"> */</span>
<span class="synType">int</span>
lwp_create(lwp_t *l1, proc_t *p2, vaddr_t uaddr, <span class="synType">bool</span> inmem, <span class="synType">int</span> flags,
           <span class="synType">void</span> *stack, <span class="synType">size_t</span> stacksize, <span class="synType">void</span> (*func)(<span class="synType">void</span> *), <span class="synType">void</span> *arg,
           lwp_t **rnewlwpp, <span class="synType">int</span> sclass)
{
        ...

        <span class="synStatement">if</span> (isfree == <span class="synConstant">NULL</span>) {
                l2 = pool_cache_get(lwp_cache, PR_WAITOK);
                memset(l2, <span class="synConstant">0</span>, <span class="synStatement">sizeof</span>(*l2));
                l2-&#62;l_ts = pool_cache_get(turnstile_cache, PR_WAITOK);
                SLIST_INIT(&#38;l2-&#62;l_pi_lenders);
        } <span class="synStatement">else</span> {
                l2 = isfree;
                ts = l2-&#62;l_ts;
                KASSERT(l2-&#62;l_inheritedprio == -<span class="synConstant">1</span>);
                KASSERT(SLIST_EMPTY(&#38;l2-&#62;l_pi_lenders));
                memset(l2, <span class="synConstant">0</span>, <span class="synStatement">sizeof</span>(*l2));
                l2-&#62;l_ts = ts;
        }

        ...

        p2-&#62;p_nlwpid++;
        <span class="synStatement">if</span> (p2-&#62;p_nlwpid == <span class="synConstant">0</span>)
                p2-&#62;p_nlwpid++;
        l2-&#62;l_lid = p2-&#62;p_nlwpid;
        LIST_INSERT_HEAD(&#38;p2-&#62;p_lwps, l2, l_sibling);
        p2-&#62;p_nlwps++;
}
</pre>

			<p><del datetime="2010-02-09T10:26:34+09:00">つまり推測するに、LIST_INSERT_HEAD(&p2-&#62;p_lwps, l2, l_sibling) で、l2 の next が 3 を指したまま insert してしまっているのではあるまいか。その結果、あとで pthread_cond_wait した時に存在しない lwpid 3 を見に行って困る、と。</p>
			<p>ちなみに、回避法はあって、pthread_createを十分な数作って捨てることで、欠番になっている lwpid を使った上で消せばよい（ぉ</del></p>
			<h4>workaround</h4>
			<p><a href="http://redmine.ruby-lang.org/issues/show/2724" target="_blank">Bug #2724</a> に書いたパッチを Ruby 1.9 に当てることで回避できます。</p>
			<h4>send-pr</h4>
			<p><a href="http://www.netbsd.org/cgi-bin/query-pr-single.pl?number=42772" target="_blank">http://www.netbsd.org/cgi-bin/query-pr-single.pl?number=42772</a> How to Repeat と Fix を使いそこねた</p>
			<h4>謝辞</h4>
			<p>この問題の解決には <a href="http://twitter.com/_enami/status/8800867968" target="_blank">@_enami さんの助け</a>がありました。</p>
		</div>
]]></description>

			<dc:creator>nurse</dc:creator>

			<pubDate>Sun, 07 Feb 2010 12:12:33 GMT</pubDate>




		</item>

		<item>
			<title>スレッドのスタック領域情報の取得</title>
			<link>http://d.hatena.ne.jp/nurse/20100204#1265266565</link>

			<description><![CDATA[
		<div class="section">
			<p>Unix 系でもそれぞれ異なるので調べた。</p>
			<p><a href="http://www.nminoru.jp/~nminoru/programming/stackoverflow_handling.html" target="_blank">スタックオーバーフローのハンドリング (Stack Overflow Handling)</a></p>
			<h4>Linux</h4>
			<h5>manpage</h5>
			<p><a href="http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_getattr_np.3.html" target="_blank">pthread_getattr_np(3)</a></p>
			<h5>header</h5>
			<ul>
				<li>#define _GNU_SOURCE</li>
				<li>pthread.h</li>
			</ul>
			<h5>API</h5>
			<p>int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);</p>
			<h5>main thread</h5>
			<p>getrlimit(2) 可、LinuxThreads では pthread_*_np 不可。</p>
			<h4>FreeBSD, DragonFly BSD</h4>
			<h5>manpage</h5>
			<ul>
				<li><a href="http://www.freebsd.org/cgi/man.cgi?query=pthread_attr_get_np&apropos=0&sektion=0&manpath=FreeBSD+8.0-RELEASE&format=html" target="_blank">pthread_attr_get_np(3)@FreeBSD</a></li>
				<li><a href="http://leaf.dragonflybsd.org/cgi/web-man?command=pthread_attr_get_np&section=ANY" target="_blank">pthread_attr_get_np(3)@DragonFly</a></li>
			</ul>
			<h5>header</h5>
			<ul>
				<li>pthread_np.h</li>
			</ul>
			<h5>API</h5>
			<ul>
				<li>int pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst);</li>
			</ul>
			<h5>main thread</h5>
			<p>pthread_*_np のみ。getrlimit(2) 不可。</p>
			<h5>NOTE</h5>
			<p><a href="http://lists.freebsd.org/pipermail/freebsd-hackers/2008-January/022916.html" target="_blank"> Initial thread stack size (Was: postgresql port, link with libc_ror not?)   </a></p>
			<h4>NetBSD</h4>
			<h5>manpage</h5>
			<p>なし</p>
			<h5>header</h5>
			<ul>
				<li>pthread.h</li>
			</ul>
			<h5>API</h5>
			<ul>
				<li>int pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst);</li>
			</ul>
			<h5>main thread</h5>
			<p>pthread_*_np、getrlimit 共に可。</p>
			<h4>OpenBSD</h4>
			<h5>manpage</h5>
			<p><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=pthread_stackseg_np&apropos=0&sektion=0&manpath=OpenBSD+Current&arch=i386&format=html" target="_blank">pthread_attr_getstacksize(3)</a></p>
			<h5>header</h5>
			<ul>
				<li>pthread_np.h</li>
			</ul>
			<h5>API</h5>
			<p>int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize);</p>
			<h5>main thread</h5>
			<p>未調査</p>
			<h4>Mac OS X</h4>
			<h5>manpage</h5>
			<p>なし</p>
			<h5>header</h5>
			<ul>
				<li>pthread.h</li>
			</ul>
			<h5>API</h5>
			<p>size_t pthread_get_stacksize_np(pthread_t);</p>
			<p>void * pthread_get_stackaddr_np(pthread_t);</p>
			<h5>main thread</h5>
			<p>getrlimit(2) を用いる。pthread_*_np 不可。</p>
		</div>
]]></description>

			<dc:creator>nurse</dc:creator>

			<pubDate>Thu, 04 Feb 2010 06:56:05 GMT</pubDate>




		</item>

		<item>
			<title>[%ruby]観察日記 2010-02-03</title>
			<link>http://d.hatena.ne.jp/nurse/20100203#1265186106</link>

			<description><![CDATA[
		<div class="section">
			<h4>RubySpecの人に怒られた</h4>
			<p>あまりに頭の悪いミスなのでぐうの音も出ない。</p>
			<h4>library/socket/tcpserver/gets_spec.rb で止まる</h4>
<pre class="syntax-highlight">
<span class="synIdentifier">Thread</span>.new { sleep }
<span class="synIdentifier">TCPServer</span>.new(<span class="synConstant">0</span>).gets
</pre>

			<p>mameさんが追跡中</p>
			<h4>FreeBSDでGC中にSEGV</h4>
<pre class="syntax-highlight">
e = [<span class="synConstant">1</span>,<span class="synConstant">2</span>,<span class="synConstant">3</span>].each
<span class="synConstant">10000</span>.times {
  e = [e].each
}
<span class="synIdentifier">Thread</span>.new { <span class="synIdentifier">GC</span>.start }.join
</pre>

			<p>がFreeBSDで落ちる。FreeBSD はメインスレッドのマシンスタックのサイズの取得方法が違うらしい。DragonFlyBSDも同様のようだ。r26549,r26550 <a href="http://www.nminoru.jp/~nminoru/programming/stackoverflow_handling.html" target="_blank">スタックオーバーフローのハンドリング (Stack Overflow Handling)</a></p>
			<h4>dlがlibffiで置き換えられた</h4>
			<p>Solaris (Sun Studio 11) や mswin32/mswin64 で dl が使えなくなってしまった。LLVM/clangでは動いた。</p>
			<p>まつもとさんは「mswin32 が解決すれば」「まぁ，いいんじゃない」だそうなので、mswin32/mswin64 対策が行われれば、1.9.2 に入ると思われる。</p>
		</div>
]]></description>

			<dc:creator>nurse</dc:creator>

			<pubDate>Wed, 03 Feb 2010 08:35:06 GMT</pubDate>



			<category>%ruby</category>


		</item>

		<item>
			<title>[%ruby]観察日記 2010-02-01</title>
			<link>http://d.hatena.ne.jp/nurse/20100202#1265042665</link>

			<description><![CDATA[
		<div class="section">
			<h4>RubySpecのバグの潰し方</h4>
			<blockquote>
			<p>(mame) <a href="http://regional.rubykaigi.org/tokyo03" target="_blank">http://regional.rubykaigi.org/tokyo03</a> 豪華講師陣だな</p>
			<p>(hermit_) 東京Ruby会議03 - Regional RubyKaigi [text/html; charset=utf-8]</p>
			<p>(ko1_ndk) mameさん講師やればいいのに</p>
			<p>(mame) 話すことないし</p>
			<p>(ko1_ndk) RubySpecのバグの潰し方</p>
			<p>(mame) 1. rubyspec を変える</p>
			<p>(mame) 以上</p>
			</blockquote>
			<p>わたしも今日数十個ほどバグを潰したんですが、全てRubySpec側の修正でした。というわけで、現在RubySpecの失敗は36個です。</p>
			<h4>RubyVMのソースコードの見方</h4>
			<blockquote>
			<p>(kosaki) すると、RubyVMのソースコードの見方が分かるんですね。わかります</p>
			<p>(shyouhei) VMのソースコードの読み方はマジ不明</p>
			<p>(ko1_ndk) なん，だと</p>
			<p>(shyouhei) まず1.3くらいのソースを、一回読んで、基礎知識をたくわえて、</p>
			<p>(shyouhei) それでもちょとまだむずい。</p>
			<p>(mame) vm.c はささださんの牙城</p>
			<p>(mame) dfp とか lfp とかの不変条件をすぐに忘れるのと</p>
			<p>(mame) 全体的に何のためにその処理をしているのかわからないところが多くて困る</p>
			<p>(ko1_ndk) なるほど</p>
			<p>(shyouhei) 全体理解のためにはinsns.defからなにがどうなってvm.oまで到達するかがMakefile読まんと分からんのが。</p>
			<p>(ko1_ndk) そのネタで yarv maniacs を書くか</p>
			<p>(mame) vm_exec が難しい</p>
			<p>(shyouhei) 「1時間で読むmatzruby」</p>
			<p>(mame) 今は 30% くらいはわかってるけど</p>
			<p>(ko1_ndk) 1.8 よりも簡単だと思うんだがなあ＞VM</p>
			<p>(mame) 1.8 は読んだことないのでしらない</p>
			<p>(shyouhei) 1.8は読み始めるハードルは低いが、読んだからといって理解はできない。</p>
			<p>(kosaki) 意図が謎すぎるということ？</p>
			<p>(shyouhei) ruby 1.8はsetjmp/longjmpが乱舞してどっからどこにいくのかまったく分からない素敵コードです。</p>
			</blockquote>
			<p><a href="http://jp.rubyist.net/magazine/?0006-YarvManiacs" target="_blank">YARV Maniacs</a>はRuby 1.9の実行系を読む人にはバイブルと言ってもいいのではないのでしょうか。まず、全容が分からないと部分を読んでもさっぱり分からないので。まぁ、そんな難解なYARVですが、eval.cやthread.cがVMから分離したのは福音だと思っています。あ、もちろんわたしはさっぱりです。</p>
			<h4>互換性〜ブラウザ編</h4>
			<p><a href="http://shinh.skr.jp/m/?date=20100201#p02" target="_blank">IEにあわせて</a> の話。HTML5とか最近の仕様はこの手の互換性維持のためのアルゴリズムが仕様注に記載されていて、もう。</p>
			<h4>Enumerable#interleave</h4>
			<blockquote title="http://twitter.com/yukihiro_matz/status/8504330947" cite="http://twitter.com/yukihiro_matz/status/8504330947">
			<p>Enumerable＃interleave というメソッドを実装してみた。flattenしたzipという感じだが、欲しい人いる？</p>
			<cite><a href="http://twitter.com/yukihiro_matz/status/8504330947" target="_blank">http://twitter.com/yukihiro_matz/status/8504330947</a></cite></blockquote>
			<p>そういうのが欲しい人にはチャンスだと思います。</p>
		</div>
]]></description>

			<dc:creator>nurse</dc:creator>

			<pubDate>Mon, 01 Feb 2010 16:44:25 GMT</pubDate>



			<category>%ruby</category>


		</item>

	</channel>
</rss>
