すごい久々にイベントの(共同)主催的なことをしました
http://connpass.com/event/34995/
イメージとしては言語雑談会的な感じで、closedに人集めてウダウダやるつもりだったんですが、途中でPFNさんに場所貸していただけるということで、不特定な人を呼ぶことになって、当初想定してたより大袈裟な会になりました。適当に募集すると人が集まって自己顕示欲が満たされるとか、普段得られない種類のフィードバックが得られたり交流ができる、てのがあるわけですが、めんどくさいのとグダグダ雑談がしにくいのが難点ですね。まあ自分自身が一般的に募集されてる会で勉強した面もあるわけで、そういうのの恩返しになるかもという面もあり、まあ色々。
まとめとしてはkoieさんのブログやtogetterがまとまってそう
http://blog.livedoor.jp/hkoie/archives/55525878.html
私の発表は
http://shinh.skr.jp/slide/kati_sp/000.html
ここに既に書いたことはざっくり飛ばして(それでも結構時間を使ってしまったけど…)、その後の細かいけど全体としてはそれなりに効いた最適化とか、straceいじって依存解析するプログラムを書いたような話をしました。後者の dsan のコードと改造 strace は
https://github.com/google/kati/tree/dsan/tools
https://github.com/shinh/strace
にあります。 dsan_record.py の方はコマンドをラップして入出力を記録できる感じになってます。
このコンセプトのドキュメントは https://docs.google.com/document/d/1eRSNE352rA6ocyoFljHQW2ySdhg9oKN8CHj2ljrlKX0/edit#
@mkasaharaさんのLD_PRELOADベースの依存解析は、LD_PRELOADというかlibcレイヤでファイルシステムAPIフックするってのは、色んな機会に既に5回とかそれ以上やったことあって、手軽で高速なんだけど、結構問題も多いと認識してたので使いませんでした。具体的な問題としては、再入してウゲーとか、fts_openみたいなあまり使われないlibc API対応とか、ダイナミックローダを始めとしたスタティックリンクされてるバイナリに無力とか。LD_PRELOADベースな話として、djbのredoというアイデアを(僕から見れば中途半端に)実装した https://github.com/jekor/redo 、 https://github.com/apenwarr/redo 、あと @kazuho さんの https://github.com/kazuho/unco なんかも一応先行研究として眺めた記憶があります。 strace ベースの(これまた不完全な)やつだと https://github.com/nickstenning/trojans/blob/master/fabricate.py とか https://github.com/kgaughan/memoize.py/blob/master/memoize.py とか。
印象に残った話
@herumiさんの話: 途中に出てきた実行ファイル電子透かしは http://www1.cs.columbia.edu/~angelos/Papers/hydan.pdf とか先行研究が。
@tanaka_akrさんの話: Unix domain socketみたいな難しいAPIじゃなくてLinuxだけにしぼっても、EPERMとEACCESとENOTDIRとENOENTはどれが優先されるの…みたいなの難しいなあ…と2年ほど前に思ってたのを思い出しました。
@kumagiさんの話: L1と分岐予測のトレードオフてのはなるほどなぁ…とか
@hogegashiさんの話: signal話、こういう話好きなのだった。こういうの好きな人は http://pwnable.kr/ の tiny_hard やるといいと思う
@yamasaさんの話: 面白いなあと思うものの、まあ護身完成してればだいたいmutex使うよねという感も
懇親会含めて思ったのは、ネットワークとDBはさっぱりわかってないな…ということでした。
おまけでシステムプログラミングクイズとか
http://shinh.skr.jp/quiz/sp.html
1問目は EAX への代入で上位32bitがクリアされるよ、というのが題意です。 AX への代入ではだめ。
2問目は、「デバッグバイナリじゃないとシンボルが見れない」とか、「バックトレースが取れない」とかたまに聞くので…
3問目だけ異常難易度でした。第一引数が間違ってるので、第三引数の 2 は処理されないため、 [1] が戻ります。
4問目はspurious wakeupについて。
5問目はgenerationalも入れても良かったですね。
tweetした、 if (*p != 42) なのに printf してみると 42 って出るってコード
https://twitter.com/shinh/status/749272046924754945
#include <stdio.h> __attribute__((noinline)) int func(int x, int y) { int* p = new int; if (*p != 42) printf("*p was not 42!!! *p=%d\n", *p); return y; } int main() { func(0, 42); }
*p の値は初期化されてないため、未定義です。「未定義!=42」をclangはtrueにするみたいです。 printf の第二引数は未定義なため、第二引数に使うレジスタである RSI は全く変更されません。また、 p は未定義なまま一切使ってないため、 new 自体が消えてなくなります。よって、 func の第二引数のために RSI にセットされた 42 がそのまま残り、件の結果になります。
あと難しいクイズとして
http://shinh.skr.jp/quiz/signature.html
http://shinh.skr.jp/quiz/stdio.html
もあります。前者は異常にむずいです。後者は @unak さんの RubyIO の話 を聞きながら作ったものです。