Showing posts with label un*x. Show all posts
Showing posts with label un*x. Show all posts

Wednesday, December 2, 2020

komake: Make の -j オプションに潜む罠とその解決策

ビルドツールのダジャレの大家と言えば @shinh さんですが、それはさておき、皆さんは今でも Make を使ってビルドすることが多いと思います。かく言う私も、その一人。

最近は CPU のコア数も多いですから、当然 -j 16 とか、やりたいわけです。大きいプロジェクトになればなるほど、威力絶大ですね。

ですが、ここで問題がひとつ。大規模プロジェクトでは Makefile が別の Makefile を呼び出すような依存関係が良く見受けられます。この際、ターゲット間の依存関係で菱形が存在すると(例: ターゲット sub1 と sub2 が shared に依存)、make shared が make sub1 と make sub2 から同時に起動されることが起こりえます。CMake で生成した Makefile の場合も、ターゲット毎に make を起動しますね。

二重起動が発生すると、ほとんどの Makefile は、同時起動されることを想定していませんから、ビルドは失敗したり、成果物が壊れたりしてしまいます。

実際に、以下のような Makefile を書いてみると、make shared が同時に動いてしまうことを確認できます(sleep 1が2回表示されていることに注目)。

$ cat Makefile
all: proj
proj: sub1 sub2
	touch $@
sub1:
	$(MAKE) shared
	touch $@
sub2:
	$(MAKE) shared
	touch $@
shared:
	sleep 1
	touch $@
clean:
	rm -f proj sub1 sub2 shared

$ make -j2
/Applications/Xcode.app/Contents/Developer/usr/bin/make shared
/Applications/Xcode.app/Contents/Developer/usr/bin/make shared
sleep 1
sleep 1
touch shared
touch shared
touch sub1
touch sub2
touch proj

どうしたらいいでしょう。

先に書いたように、問題は同一ターゲットを引数にとる make が重複起動されてしまうところです。ならば、make の並走度を別途制限すればいいのではないでしょうか。ある make が終了するためには、その make が呼び出した make が全て終了している必要があることを加味すると、単純に、呼び出し階層毎の make の同時実行数を1に制限してしまえば、この問題が解決するはずです。

ジャジャーン!!! と言うわけで書いたのが make のラッパースクリプト komake です!

わずか41行のスクリプトにして、求められる機能を実現しています。komake を使って先の Makefile を実行すると、ほら、このとおり!!!

$ komake -j2
komake shared
komake shared
sleep 1
touch shared
touch sub1
make[1]: `shared' is up to date.
touch sub2
touch proj

komake shared は2回呼び出されていますが、実際のビルド作業である sleep 1 と touch shared の呼び出しが1回に減少したことがわかります。これは、1回目の komake shared が終了した後に2回目の komake shared が呼び出され、既に「shared」ファイルが存在したから、ビルド作業は何も走らなかったからです。

完璧ですね!! すばらしい!!!!

なお、注意点として、多重起動されロックを取ろうとしている komake も make のジョブスロットを消費します。ですので、komake を使う場合には、-j オプションに渡す引数を CPU コア数 + ロックにひっかかりそうな make の数(たとえば4)等にセットするとよいでしょう。

ちなみに、名前の komake は、「こまけー問題なおしてるな」というセルフツッコミに由来します。細かな問題なのですが、大規模プロジェクトにおいて切実な make の待ち時間問題を解決する、かゆいところに手の届くツールになっていると思います。

。。。。。とか書いてるうちに、同僚の @gfx が、問題となっていたプロジェクトのビルドツールを Ninja に移行する作業を終わらせてしまいました。完敗だ。これはKO負けですね。

Wednesday, March 11, 2020

2020年にDSRロードバランス環境を作る方法

TCPの時代もそうだったんですが、QUICにおいても、Linux等でソフトウェアロードバランサをipvsadmとDSR (direct server return, a.k.a. direct routing) を実現することは有効な手段です。

なんだけど、ipvsadm界隈はHA前提の込み入った設定か古いドキュメントしか見つからなかったので、最低限の検証環境のセットアップ方法を、ここにまとめる次第です。

ロードバランサ:
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo ifconfig eth0:0 $VIP netmask 255.255.255.255 broadcast $VIP up
sudo route add -host $VIP dev eth0:0
sudo ipvsadm -A -t $VIP:443 -s rr
sudo ipvsadm -a -t $VIP:443 -r $SERVER1 -g
sudo ipvsadm -a -t $VIP:443 -r $SERVER2 -g
sudo ipvsadm -a -t $VIP:443 -r $SERVER3 -g
...

要は、フォワーディングを有効にして、自分自身へのパケットを他のサーバにフォワードするような変態行為をするからspoofing対策フィルタをオフにして、次にipvsadmでテーブル作ってサーバ追加する。

サーバ:
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
echo 0 | sudo tee /proc/sys/net/ipv4/conf/eth0/rp_filter 
echo 2 | sudo tee /proc/sys/net/ipv4/conf/eth0/arp_announce
echo 1 | sudo tee /proc/sys/net/ipv4/conf/eth0/arp_ignore
sudo ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $VIP up
sudo route add -host $VIP dev lo:0

要は、フォワーディング有効にして、VIPがARPでアナウンスされたり、応答したりしないように設定して、loにVIPをつけて、eth0で受信したパケットがlo:0に転送されるように設定する。

これで動く。

Thursday, June 14, 2018

Git で全ブランチから検索

ググったけどmacOSでぱっと動くのがなかったのでメモがてら書く。

全ローカルブランチから検索
% git grep keyword $(git branch | colrm 1 2)

リモート含む全ブランチから検索
% git grep keyword $(git branch -a | colrm 1 2)

Tuesday, October 6, 2015

[メモ] OS XのホストからVMにnfsでファイル共有

普段OS X上で作業しつつ、開発ディレクトリをOS X上のVMで動いているLinuxやFreeBSDからもアクセスできるようにしてあると、互換性検証がはかどる。

どう設定するか、備忘録をかねてメモ。

1. ゲスト側で通常使用するアカウントのuser-id,group-idを、OS Xのそれに揃える

2. OS Xの/etc/exportsと/etc/nfs.confを以下のように、TCP経由でVMの仮想ネットワークにだけファイルを公開するよう設定
/etc/exports:
/shared-dir -mapall=user:group -network netaddr -mask netmask

/etc/nfs.conf:
nfs.server.udp=0
nfs.server.tcp=1
3. ゲスト側の/etc/fstabにマウント情報を設定
192.168.140.1:/shared-dir /shared-dir nfs rw,noatime 1 0
これで、ホストでも、どのVMでも、/shared-dirの中身が同じになる。

注. VMware Fusion 10の場合は、環境設定から、新しいネットワークを作成し、「NATを使用する」を外し、そのネットワークを使う必要がある。そうしない限り、ホストに見えるTCPのソースアドレスがローカルネットワークのものにならない。

できるだけ単純に構成しようとすると、こんな感じになるかな、と。設定に問題があるようだったら教えてください。

Wednesday, September 30, 2015

H2O version 1.5.0 released

Today, I am happy to announce the release of H2O version 1.5.0.

Notable improvements from 1.4 series are as follows:

On-the-fly gzip support

This was a feature requested by many people, and I would like to thank Justin Zhu for doing the hard work!

mruby-based scripting

Server-side scripting using mruby is now considered production level.
And now that the our API is base on Rack, it would be easy for Ruby programmers to use / learn, thanks to its excellent design and documentation.

For this part, my thank you goes to Ryosuke Matsumoto, Masayoshi Takahashi, Masaki TAGAWA.

cache-aware server push

Server-push is an important aspect of HTTP/2, however it has generally believed to be hard to use, since web application do not have the knowledge of what has already been cached on the client-side.

With the help of Ilya Grigorik and the Japanese HTTP/2 community, we have essentially solved the issue by introducing cache-aware server push; the server is now capable of tracking the what the web browser has in its cache, and determine whether or not a resource should be pushed!

We plan to improve the feature in the upcoming releases so that the Web can be even faster!

isolation of private keys

H2O now implements privilege isolation for handling RSA private key operations so that SSL private keys would not leak in case of vulnerabilities such as Heartbleed.


In the upcoming days I will post several blogposts explaining the notable changes. Stay tuned.

Thursday, September 24, 2015

Neverbleed - RSAの秘密鍵演算を別プロセスに分離する話

機能毎にプロセスを分割し、それらを別個の権限のもとで実行することで、脆弱性があった場合の影響を抑え込むというのは、一定以上の規模をもつプログラムでは、しばしば見られるデザインパターンです。

qmailは、そのような設計がなされたメール配送デーモンとして名高いですし、OpenSSHもまた、認証プロセスと通信プロセスを分離することで、外部との通信を担当するコードにバグがあったとしても、ルート権限が奪われないように設計されています(参照: Privilege Separated OpenSSH)。

一方で、OpenSSLにはそのような権限分離は実装されていません。Heartbleedの際にサーバの秘密鍵が漏洩したのも、秘密鍵の取り扱いと、その他の通信の取り扱いを同一のメモリ空間の中で行っていたからだと考えることができます。

ないのなら、自分で作ればいいじゃない…ということで作りました。それが、Neverbleedです。

Neverbleedは、OpenSSLの拡張インターフェイスであるEngineを利用して、RSA秘密鍵を用いる処理を専用プロセスに分離します。OpenSSLの初期化時に専用プロセスを起動し、秘密鍵の読み込みと関連演算は全て専用プロセスで行われるため、OpenSSLを利用するサーバプロセスに脆弱性があったとしても秘密鍵が漏洩することはありません。

OpenSSLの拡張インターフェイスを利用しているため、OpenSSLへの変更は不要ですし、サーバプログラムへの変更もごく少量ですみます。また、専用プロセスとの通信のオーバーヘッドはRSAの秘密鍵演算と比べると非常に小さいため、そのオーバーヘッドは問題になりません。

そんな感じでうまく動いているので、Neverbleedは、今月リリース予定のH2Oバージョン1.5に組み込まれる予定です。

参照: http://www.citi.umich.edu/u/provos/ssh/privsep.html

Thursday, May 14, 2015

jailing - chroot jailを構築・運用するためのスクリプトを書いた

個人サーバで外部に公開するサービスを動かすときには、chrootを使うにこしたことはないわけです。サービス毎にchrootしてあれば、サーバソフトウェアにセキュリティホールがあっても、他の情報が漏洩したりする可能性をぐっとおさえることができるわけですから。

でも、そのためだけにVPSにdockerとかコンテナを入れて使うってのは、構築も運用もめんどくさいし、ディスク容量食うし、やりたくない。systemd-nspawnも割と重たい雰囲気だし、LTSなubuntuだとそもそもsystemd入ってないし…

俺たちがほしいのは、ホストの環境の一部のみにアクセスできる、手軽なjailだー! ってわけで、ざっくり書いたのが、jailing。

github.com/kazuho/jailing

/usr/bin等、OS由来のディレクトリをchroot環境にread-onlyでエクスポートしつつ、指定されたコマンドを、そのchroot環境で動かすスクリプトです。

/usr/localや/homeといったディレクトリはエクスポートしないので、chroot環境下のソフトウェアにセキュリティホールがあって侵入されたとしても、(カーネルにバグがなければ)chroot環境外の情報が漏洩することはありません。

ホストとchroot環境でディレクトリを共有するためには、--bindオプションを使います。

たとえば、/usr/local/apache下にインストールしたApacheをchroot環境下で動かしたいなって時、jailingを使えば、以下のようにコマンド一発でchroot環境を作成して実行できます。
% sudo jailing --root=/var/httpd-jail \
    --bind /usr/local/apache \
    -- \
    /usr/local/apache/bin/httpd \
    -c /usr/local/apache/conf/httpd.conf
あるいは、/usr/local/h2o下にインストールしたH2Oをchroot環境下で動かす場合は、こんな感じ。
% sudo jailing --root /var/h2o-jail \
    --bind /usr/local/h2o \
    -- \
    /usr/local/h2o/bin/h2o \
    -m daemon \
    -c /usr/local/h2o/etc/h2o.conf
あるいは、jail内に入るには、
% sudo jailing --root /var/h2o-jail \
    -- \
    bash
とかやればいいわけです。

簡単ですね!

詳しくはman jailingしたりしてください。それでは〜

Monday, May 11, 2015

Clangに対応し、より高速になったqrintf version 0.9.2をリリースしました

ひさしぶりにqrintf関連の作業を行い、バージョン0.9.2をリリースしました。

ご存知のように、qrintfは、ccachedistccと同様の仕組みでCコンパイラのラッパーとして動作する、sprintf(とsnprintf)の最適化フィルターです。

qrintfを利用することで、整数や文字列をフォーマットするsprintfやsnprintfは最大10倍高速化され、また、H2Oのようなhttpdが20%程度高速化することが知られています。

今回のリリースは、0.9.1以降に行われた以下の改善を含んでいます。


以下の実行例からも、GCCでもClangでもIPv4アドレスの文字列化ベンチマークにおいて、qrintfを利用することで10倍以上の高速化が実現できていることが分かります。
$ qrintf --version
v0.9.2
$ gcc -O2 examples/ipv4addr.c && time ./a.out 1234567890
result: 73.150.2.210

real 0m2.512s
user 0m2.506s
sys 0m0.003s
$ qrintf gcc -O2 examples/ipv4addr.c && time ./a.out 1234567890
result: 73.150.2.210

real 0m0.173s
user 0m0.170s
sys 0m0.002s
$ clang -O2 examples/ipv4addr.c && time ./a.out 1234567890
result: 73.150.2.210

real 0m2.487s
user 0m2.479s
sys 0m0.004s
$ qrintf clang -O2 examples/ipv4addr.c && time ./a.out 1234567890
result: 73.150.2.210

real 0m0.220s
user 0m0.214s
sys 0m0.002s

今後は、qrintfをH2Oにバンドルすることで、qrintfの恩恵をより多くの利用者に届けて行きたいと考えています。同様のことは、他のソフトウェアプロジェクトでも可能なのではないでしょうか。

それでは、have fun!

Tuesday, March 24, 2015

released Server::Starter 0.21; no more external dependencies, easy to fat-pack

I am happy to announce the release of Server-Starter version 0.21.

In the release I have removed dependencies to perl modules not in core (e.g. Proc::Wait3, List::MoreUtils, Scope::Guard).

Without dependencies on XS modules it would now be easier to install the module on any system.

The change also opens the possibility to fat-pack the `start-server` script; it can be accomplished by just running the fatpack-simple script.
$ fatpack-simple start_server
-> perl-strip Server/Starter.pm
-> perl-strip Server/Starter/Guard.pm
-> Successfully created start_server.fatpack
$ 

Have fun!

Tuesday, February 17, 2015

Writing signal-aware waitpid in Perl

As I have talked in YAPC::Asia couple of years ago, the wait functions (e.g. wait, waitpid) of Perl do not return EINTR when receiving a signal.

This is a problem if you would want to wait for child processes until receiving a signal. Proc::Wait3 can be a solution, however the module may be hard to install as it is an XS module. It should also be noted that the module provides replacement for wait only; no workaround exists for waitpid.

So today I have scrubbed my head wondering if I could come up with a pure-perl solution, and, here it is. The Perl script below launches a worker process (that just sleeps), and waits for the process to complete, or until SIGTERM is being received.

use strict;
use warnings;
use Errno ();

our $got_sigterm = 0;
our $sighandler_should_die = 0;

# fork a child process that does the task
my $child_pid = fork;
die "fork failed:$!"
    unless defined $child_pid;
if ($child_pid == 0) {
    # in child process, do something...
    sleep 100;
    exit 0;
}

$SIG{TERM} = sub {
    $got_sigterm = 1;
    die "dying to exit from waitpid"
        if $sighandler_should_die;
};

warn "master process:$$, child process:$child_pid";

# parent process, wait for child exit or SIGTERM
while (! $got_sigterm) {
    if (my_waitpid($child_pid, 0) == $child_pid) {
        # exit the loop if child died
        warn "child process exitted";
        $child_pid = -1;
        last;
    }
}

if ($child_pid != -1) {
    warn "got SIGTERM, stopping the child";
    kill 'TERM', $child_pid;
    while (waitpid($child_pid, 0) != $child_pid) {
    }
}

sub my_waitpid {
    my @args = @_;
    local $@;
    my $ret = eval {
        local $sighandler_should_die = 1;
        die "exit from eval"
            if $got_sigterm;
        waitpid($args[0], $args[1]);
    };
    if ($@) {
        $ret = -1;
        $! = Errno::EINTR;
    }
    return $ret;
} 

The trick is that waitpid is surrounded by a eval within the my_waitpid function, and the signal handler calls die to exit the eval if the $sighandler_should_die flag is being set. It is also essential to check the $got_sigterm flag within the eval block after setting the $sighandler_should_die flag, since otherwise there would be a race condition.

By using these tricks it has now become possible to implement process managers in pure-perl!

Thursday, January 15, 2015

[メモ] TCP上(もしくはHTTP)にリトライ可能なアプリケーションプロトコルを実現する方法

HTTP/1.1の持続的接続においては、サーバがリクエストを受け取ったあとに異常終了したのか、リクエストを受け取らずに接続を閉じたのか判別することができない。このため、べき等性の保証がないアプリケーションにおいて、リトライを行うべきか否か自動的に判断できなくなる場合がしばしば発生する

リトライ可能か否か(ピアがメッセージの処理を開始した否か)を判別するには、より細かな情報交換を行う別種のプロトコルを採用しても良いが、複雑なプトロコルはパフォーマンスに悪影響を及ぼす可能性が高いので避けたいところである。

というわけで、以下本題。

pipeliningを行わないHTTP/1.1のような単純なリクエスト/レスポンス型プロトコルをそのままに、アプリケーションレイヤへのリクエスト到達可否を判定する手軽な方法としては、SO_LINGERを用いる方法がある。具体的には、以下のような形式でサーバを実装する。
while (1) {
  receive_request();
  use_RST_for_close(); // SO_LINGERを使い、RSTで切断するよう設定
  handle_request();
  send_response();
  use_graceful_close(); // SO_LINGERを使い、graceful closeを行うよう設定
}
クライアントサイドでは、リクエスト送信後にEPIPE(write(2)の場合)かECONNRESET(read(2)の場合)を受け取った場合のみ、リクエストを再送すればよい。

別解としては、サーバが接続を切断する際に「HTTP/1.1 599 Going Away」のようなレスポンスを(たとえリクエストを受信していなくとも)送信するという方法が考えられる(この場合はlingering closeを行わない)。クライアントは、サーバからこのレスポンスを受信した場合のみ、リクエスト再送を行えば良い。

追記: H2Oでは後者の方式をサポートしようかと考えている。そうすれば「Docker と SO_REUSEPORT を組み合わせてコンテナのHot Deployにチャレンジ - blog.nomadscafe.jp」で挙げられているようなデプロイ手法において、(例示されている常にリトライする方法とは異なり)安全なホットデプロイが実現可能になる。

注: パイプライン処理については行わない前提で考える

Monday, December 8, 2014

64bit時代のバッファ処理

プログラミングの「常識」は時代とともに変化します。そのひとつが、サーバプログラムにおけるバッファ処理です。

1990年代後半から2010年頃までは、メモリ空間の大きさ(32bitすなわち4GB注1)を超える大きさのファイルを扱う時代でした。このため、httpdなどのサーバプログラムにおいても、入出力データをいったんテンポラリファイルとしてバッファリングする必要がありました。ですが、ファイルI/Oはメモリアクセスと比べると低速です。このため、小さなサイズのデータについてはメモリアクセスする一方で、大きなサイズのデータについてはファイルI/Oを用いる、という煩雑なコードを書く必要がありました。

しかし、2014年も暮れとなる今 、サーバサイドにおいては64bit環境のみを考えれば良い時代に入りつつあります。

もちろん、64bit環境といったところで、64bit空間の全てをユーザプロセスが使えるわけではありません。現行のx86-64 CPUがサポートする論理アドレス空間は48bit(256TB相当)であり、多くのOSではその上位アドレス半分がカーネル空間に割り当てられ、残った128TBがユーザプロセスで使用可能な空間となっています注2

128TBものメモリ空間があれば、全てのテンポラリデータを「メモリ空間にマッピングして」使用することができます。

実際に、H2Oのバッファ処理では、64MBを超えるものについてはテンポラリファイルをftruncate/mmapすることで領域を確保注3し、これに対してメモリアクセスを行うようになっています。詳しくはh2o_buffer_reserve関数の定義をご覧ください。

バッファを利用する側のコードにおいては、サイズの大小に関係なく単なるメモリブロックとしてアクセスできるため、コードが単純かつ高速になるのです。

※本記事はH2O Advent Calendar 2014の一部です。

注1: 多くのOSにおいては、カーネルとメモリ空間を分け合う必要があるため、実際にユーザプロセスで使用できるメモリ空間は1GB〜3GB程度でした
注2: 参照: x86-64 - Wikipedia, the free encyclopedia - Operating system compatibility and characteristics
注3: malloc(3)で確保可能なメモリの総量である物理メモリ+スワップ領域の和は必ずしも十分に大きくないため、テンポラリファイルを生成してftruncateすることでディスク上に必要な領域を確保しています

Tuesday, November 4, 2014

The internals H2O (or how to write a fast server)

Yesterday, I had the opportunity to speak at the HTTP2Conference held in Tokyo.

Until now, I have rather been silent about H2O since I think it is still premature for wild use. But you do not need to worry about such thing in a technology conference, so I happily talked about the motives behind H2O, and its implementation.

IMO the talk should be interesting not only to people working with HTTP server implementations but also to those interested in programming in general, since it covers the common performance pitfalls (or misconceptions as I see) in many server implementations.

Below are the slides and the recorded video of my presentation.

Enjoy!

PS. Please forgive me for the provocative attitude in the questions raised in the last part of the slides. They were intentionally written as such in order to spark discussion at the hall.



my talk starts a 3h15m (in Japanese)

Related links:

Friday, October 10, 2014

[メモ] root権限でrsyncする方法

サーバの移転作業時など、rootしかアクセスできない設定ファイルやアクセス権を保ったままrsyncしたいことってありませんか?

そういった際には、sudo の -A オプションと rsync の --rsync-path オプションを使うと良いようです。

まず、リモートサーバに、パスワードを標準出力に出力するスクリプトファイルを配置します(ファイルのパーミッションを厳しくするのを忘れずに)。
% cat > bin/askpass
#! /bin/sh
echo "{{my_password}}"
% chmod 700 bin/askpass
% 
そして、rsync を実行する際には --rsync-path オプションを使い、リモートサーバの rsync を sudo -A 経由で起動するようにすれば良いのです。
% sudo rsync -avz -e ssh \
    --rsync-path='SUDO_ASKPASS=/home/remote-user/bin/askpass sudo -A rsync' \
    remote-user@remote-host:remote-dir local-dir

これは簡単!

sudo -Aオプションはパスワードを記述したファイルを設置する必要があるという点でNOPASSWD同様セキュリティの懸念はありますが、使いどころを誤らなければ便利だなと思いました。

Thursday, June 5, 2014

Unix系OSの権限分離の変遷について(もしくはなぜ、アプリ単位の権限分離が求められるようになったか)

[ブコメした件について。大筋でおかしなことは書いてないと思いますが、出典は確認していません]

Unix系OSにおける権限分離は、伝統的に、利用者ごとに異なるuser idを割り振り、これを用いてアクセス制御を行うという方式で実現されてきた。また、デーモンプロセスについては、不要な権限付与を避け、デーモンプロセス間の相互作用を抑制するために、デーモンごとに専用の「user id」を発番するのが一般的な慣習とされるようになったという経緯がある。

しかし、2000年代に入ると、インターネットの普及とあいまって、クライアントサイドではこのような「利用者ごと」の権限分離では不十分という考え方がされるようになってきた。具体的には、

  • (オンラインバンクのパスワードに代表されるような)攻撃価値が高い情報をOS内に保存・利用するのが一般的になった
  • (限定された流通経路で入手するソフトウェアのみならず)インターネットからダウンロードしたプログラムを実行するという慣習が一般的になった
のようにユーザー行動が変化した結果、高いセキュリティが要求される処理と、セキュリティよりも利便性を重視したい処理が、同一のアクセス権限のもとに併存するようになったのである。だが、そのような状況は危険である(ネットからダウンロードしたマルウェアによって重要な情報が流出する可能性がある)。よって、同一ユーザー権限のもとで動作するプログラム間においても、アクセス権限の分離の必要性が認められるようになってきたのだ。

このため、iOSやAndroidのようなスマホOSにおいては、利用者ごとではなくプログラムごとに異なる「user id」を割り振り、互いのデータにアクセスできないような仕組みになっている。

一方でOS Xのような、より以前からあるUnix系OSにおいては、このような仕組みに移行することは現実的でないため、Keychainのように、秘匿性の高い情報についてのみプログラム単位でのアクセス制御機能を提供することで、問題の緩和が計られている。

以上のような経緯があるので、クライアント上で一般ユーザー権限で動作するプログラムにおいて、(psコマンド等を通じて情報が流出する問題がある)環境変数に認証情報を格納するのは避けるべきと言えるだろう。

Friday, April 11, 2014

[メモ] Starlet 0.22のリリースに伴いThundering Herd問題を再訪した件

@takezawaさんから、PerlベースのWebアプリケーションサーバであるStarletで複数ポートをlistenできるようにするPRをいただいたのでマージしました。やったね!

で、それに伴いprefork型TCPサーバのThundering Herd問題を再訪したので、その備忘録。なお、Thundering Herd問題については、prefork サーバーと thundering herd 問題 - naoyaのはてなダイアリーや、Starman と Starlet のベンチマークと Accept Serialization - Hateburo: kazeburo hatenablogあたりを参照のこと。

まず、こんなテストスクリプトを書いた: thundering-herd.pl

こいつを書いてあるコメントのとおり実行してみることで、2種類のケースでThundering Herd問題が存在するか調べることができる。

で、こいつを使った結果、以下の結論に達した。
  • accept(2)の呼出によるThundering Herd問題だが、多くの環境で過去の問題になったと考えてよい
  • select(2)で接続を待ち受け、次にaccept(2)を呼ぶようなケースでは、依然としてThundering Herd問題が存在する(当然と言えば当然だが)
とか言ってみたけど、、linux 2.6.32とOS X 10.8.5でしかテストしてないので、補足あれば教えてください m(__)m

あと、複数のポートにbind(2)するTCPサーバを書く際に注意すべき点として、prefork型サーバでselect(2)accept(2)の呼出順序で接続を確立する際は、ソケットをnonblockingモードにしておかないと、ワーカプロセスが余っているのに接続できないといった事態が発生する可能性がある。

この点は、上記のテストスクリプトを書くまでレビューするのを忘れていたんだけど、確認したらtakezawaさんのコードではちゃんと記述されていて、ちょっと感動した。いい仕事ありがとうございました。

Wednesday, April 2, 2014

Announcing Unco - undo changes to files made by any command

Being sick of myself occasionally wiping off the changes made to files by running wrong commands, I have started writing a program called "Unco" (pronunciation: an-ko) - a command that records the changes to the file system, and let the users undo the changes afterwards if necessary.

Unlike existing command-level solutions like aliasing rm to trash-cli, Unco is designed to be capable of undoing changes made by any program; it hooks the library calls that affect the file system and records the changes for later undoing.

The following scenario illustrates how it can be used, in case of git.
  1. instruct the shell to record all git commands
    % alias git="unco record -- git"
    
  2. edit file under the git repository
    % vi program.c
    
  3. Oops! I have accidentally reset the changes
    % git reset --hard HEAD
    
  4. don't worry, just undo the last action
    % undo history
    index    command (*=undone)
         1   git reset --hard HEAD
    % unco undo 1
    
As described, you can apply unco for rm or make install or whatever command.

The development is still in early stages, and I would not advise anybody not capable of debugging the code by oneself to use it. But for those interested, the repo is at github.com/kazuho/unco.

For the time being, the program runs on OS X and linux (edited Apr. 3 2014)only on OS X. Hopefully the command may be polished up so that it can be turned on by default; i.e. record all commands run on the shell by default.

Saturday, October 15, 2011

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy