2011年10月24日月曜日

MacPorts2.0 Xcode4.2でpostgreSQLがSegmentation Fault 11が起こり悶絶

先日、メインの開発マシンであるMac miniにLionをクリーンインストールしました。周辺ツールも、Xcode4.2・MacPorts2.0の最新版をインストールして、開発環境も順調に作成していました。

よく使うportsはコンパイルまでに正常に終わり、あとはDatabaseへデータのリストアをすれば完了だなと思っていたら、postgreSQLがデータのリストア時にSegmentation Fault 11で落ちてしまいます。やばい、これが動かないと仕事が出来ない。

...
Segmentation Fault 11
$

ちょっと焦りましたが、こういう時はgoogle先生に聞くのが一番です。ググってみるとMacPortsのバグトラッキングのページに「postgresql91 segfaults on OS X 10.7 when built with Xcode 4.2」と言う、今の状況そのまんまなバグ報告が見つかりました。

このバグ報告に付いているコメントをみると、「Xcode 4.2ではコンパイル時に/Developer/usr/bin/clangがデフォルトで使われるが、これが悪さをしているようなので/Developer/usr/bin/llvm-gcc-4.2を使った方が良い。」と書かれていたので、llvm-gcc-4.2を使ってコンパイルしてみます。

clangとはコンパイラのフロントエンドであり、llvmをバックエンドとして使用されるものらしいです。Xcode4になって、コンパイラがgccからllvmに移行したらしいので、他のポートでも色々不具合が出ているようです。

コンパイラをllvm-gcc-4.2に変更する方法は2つ有り、/opt/local/var/macports/sources/rsync.macports.org/release/tarballs/ports/databases/postgresql90/Portfileを変更する方法と、コマンドラインからコンパイラを指定する方法があります。Portfileを変更するより、コマンドラインから指定した方がお手軽なので、今回はコマンドラインで作業をしてみます。

コンパイラを変更するには下記のコマンドを実行します

$ sudo port -d install postgresql90 configure.compiler=llvm-gcc-4.2

configure.compilerには/opt/local/share/macports/Tcl/port1.0/portconfigure.tclに定義されている下記の文字列を指定できます(指定できても該当するコンパイラーがインストールされていないとエラーになりますよ。)

    switch -exact ${configure.compiler} {
        cc { set name "System cc" }
        gcc { set name "System gcc" }
        gcc-3.3 { set name "Mac OS X gcc 3.3" }
        gcc-4.0 { set name "Mac OS X gcc 4.0" }
        gcc-4.2 { set name "Mac OS X gcc 4.2" }
        llvm-gcc-4.2 { set name "Mac OS X llvm-gcc 4.2" }
        clang { set name "Mac OS X clang" }
        apple-gcc-3.3 { set name "MacPorts Apple gcc 3.3" }
        apple-gcc-4.0 { set name "MacPorts Apple gcc 4.0" }
        apple-gcc-4.2 { set name "MacPorts Apple gcc 4.2" }
        macports-gcc-4.0 { set name "MacPorts gcc 4.0" }
        macports-gcc-4.1 { set name "MacPorts gcc 4.1" }
        macports-gcc-4.2 { set name "MacPorts gcc 4.2" }
        macports-gcc-4.3 { set name "MacPorts gcc 4.3" }
        macports-gcc-4.4 { set name "MacPorts gcc 4.4" }
        macports-gcc-4.5 { set name "MacPorts gcc 4.5" }
        macports-gcc-4.6 { set name "MacPorts gcc 4.6" }
        macports-llvm-gcc-4.2 { set name "MacPorts llvm-gcc 4.2" }
        macports-clang { set name "MacPorts clang" }
        default { return -code error "Invalid value for configure.compiler" }
    }

ちなみに、コンパイルオプションを指定したい場合は、下記のようにconfigure.optflagsを追加します。

$ sudo port -d install postgresql90 configure.optflags="-O3 -pipe" configure.compiler=llvm-gcc-4.2

llvm-gcc-4.2でコンパイルしたpostgreSQLでリストアしたところ、無事に完了しました\(^O^)/ バグトラッキングでpatch fileも投稿されていたので、近々反映されるでしょう。

2011年10月11日火曜日

Glenn Gould on Television が届いた

来年は、グレン・グールドの生誕80年・没後30年と言うことで、SONY CLASSICALからCBCのアーカイヴに保管されていた19時間以上にわたるTVドキュメンタリー、演奏シーン、インタヴュー、対談などの全映像をまとめたDVD ボックスが発売されます。

Glenn Gould - The Complete Original Jacket Collectionも、以前ポッチとしてしてしまった身としては、これも買っておく他ないだろうと言うことで、amazonで予約をしました。

予定では9月末に発送の事でしたが、2週間ほど遅れて10/09に届きました。しかし、その日は仕事で修羅場の真っ最中、開けている暇も無かったのですが、ようやく一息ついたので、写真だけでもアップしておこうと思います。

まずは表紙。Import版のはずですが、何故か日本語のシールが貼ってあります。読んでみると簡単な紹介文と字幕は付いていませんと注意書きが書いてありました。

表紙

次は裏表紙

裏表紙

背表紙、薄型のケースを使っているので10枚組でもあまり場所を取りません。メディアをしまうスペースが無くなってきているので、薄型仕様は嬉しい。

背表紙

ブックレットは、最初に「Glenn Gould on Televisionの発売に寄せて」的な事が、英語・フランス語・ドイツ語(多分)で書かれています。それ以外は、各DVDの曲目が書かれているだけの簡単なものでした。

背表紙

DVD本体は至ってシンプルでした。

背表紙

今回は、記念リリースの第1弾らしいですが、2弾・3弾と出てくると財布が心配になってきます。しかし、限定版の場合は買い逃すと一生買えない可能性があるので、出たら買ってしまうのだろうな。

2011年8月2日火曜日

MacPortsのportarchivemodeが廃止された

MacPortsを再インストールでは、portarchivemodeを有効にして、複数のマシンに効率的にインストールする方法を書いたのですが、バージョンが2.0に変わってからportarchivemodeがなくなってしまいました。

portarchivemodeが無くなった代わりに、portはコンパイルする前にhttp://packages.macports.org/をチェックしてパッケージが存在する場合は、それを使うようになったみたいです。

$ sudo port install FDclone +autosort +emacs +lv
--->  Computing dependencies for FDclone
--->  Fetching archive for FDclone
パッケージを取得しているぽい。
--->  Attempting to fetch FDclone-3.00j_0+autosort+emacs+lv.darwin_10.x86_64.tbz2 from http://packages.macports.org/FDclone
--->  Fetching FDclone
--->  Verifying checksum(s) for FDclone
--->  Extracting FDclone
--->  Applying patches to FDclone
--->  Configuring FDclone
--->  Building FDclone
--->  Staging FDclone into destroot
--->  Installing FDclone @3.00j_0+autosort+emacs+lv
--->  Activating FDclone @3.00j_0+autosort+emacs+lv
--->  Cleaning FDclone

あらかじめコンパイルされたパッケージを使うようになって地球に優しくなったのですが、現状 http://packages.macports.org/ には、それほどパッケージが用意されていないので、結局はコンパイルする事になり、あまり役に立っていないのが現状です。

パッケージのFetchとportarchivemodeを両方サポートしてくれれば最高なんですけどね。今後に期待しましょう。

2011年7月31日日曜日

今年は蝉が少ない?

自分は田園都市線沿線に住んでいますが、例年よりも蝉の鳴き声が少ない気がします。毎年誰かが少ないと言っているような気もしますが、今年は地震の影響も多少あったのかなと思っています。原因として考える要因を、思いつくままにあげてみると

  1. 地震の揺れで圧縮された土に押しつぶされて圧死。
  2. 局部的な液状化で溺死。
  3. 寒いのでもう少し待っている。
  4. 8月から本気出す。
  5. 放射線の影響で巨大化している最中。
  6. 怒りの頂点に達していないので、サナギマンから脱皮できない。

例年だと、後半大量に羽化して五月蠅くなののですが、今年の8月は涼しいらしいので、少ないまま終わってしまうかも。

自分は、ミンミンゼミ・ツクツクボウシ・ひぐらし等のリズム系の鳴き声は好きなのですが、アブラゼミ等のノイズ系は嫌いなので、所々で聞こえる程度の方が返って良かったりします。

2011年7月28日木曜日

スニペットの管理ツールCodeBoxが85円だったので買ってみた。

以前から、スニペットを管理するアプリが欲しかったのですが、フリーなものだと機能が微妙な感じで、有料なものだと今度は価格面が微妙で買いあぐねていました。 今日、何となくApp Storeをのぞいてみると、CodeBoxと言うアプリが85円で売っていました(確か以前は850円だったと思うので90%off!!)。

CodeBox

CodeBoxは候補の一つに挙がっていたのですが、お試しができないのと最近作成されたアプリの様でしたので保留にしていました。でも、今回85円だったので失敗してもいい金額かなと思いポチッとしてしまいました。

まだ使い始めたばかりですが、基本的な機能は備えているようです。しばらくはこれで様子を見てみようと思います。

CodeBoxのサイトでは$9.99になっているようです。入力ミスなのかセール中なのかいまいち不明なので、欲しい人は今のうちに買っておいた方がよいかも。

2011年7月20日水曜日

64bit版emacsのwnn7eggがbackend timeoutになる件を調査してみた

emacsの64bit化を阻むもの

自宅サーバ(NetBSD 64bit)には、32bit Linux emulationでオムロンソフトウェアのWnn7が動作しています。そして、これを自宅サーバ(NetBSD)・開発マシン(Mac mini)・サブマシン(Macbook air)上のemacsから使用しています。この構成だと学習した情報をサーバー側で一元管理できるので、学習データを共有するための同期処理をどうしようかと悩む必要がなくて重宝しているのですが、以前、各マシンのemacsを64bit化しようと目論んだのだけれども、64bit化するとwnn7eggがbackend timeoutというエラーを吐いてしまい断念してしまいました。

デバッグ

まず64bit版 Emacsを"--debug"を付けて立ち上げてbackend timeoutするときのBacktraceを取って、不具合のありそうな関数に当たりをつけて32bit番の動きと違いがないか一個ずつ調べてみました。Elispのデバッグはしたことがかなったので、凄く効率が悪く面倒臭いデバッグ方法になってしまいました。

上記のやり方で調査していくと、 wnn7rpc-get-autolearning-dic関数で違いが出ることがわかりました。

  (defun wnn7rpc-get-autolearning-dic (env type)
  "Get id of auto learning dictionary on the server.
Return dictionary id + 1 on success, 0 on no dictionary, negate-encoded
error code on faiulure."
  (wnn7rpc-call-with-environment env (result)
    (comm-format (u u u) (wnn-const JS_GET_AUTOLEARNING_DIC)
                 env-id type)
    (wnn7rpc-get-result
      (comm-unpack (u) result)
      (print result)
      (1+ result))))

上記のソースのように(print result)を付加してresultの値を表示すると32bitと64bitで違いが発生します

;; 32bit Emacsで正常の場合
Wnn: connecting to jserver at foo.rfc2606.invalid.jp(22273)...done
ホスト foo.rfc2606.invalid.jp の Wnn を起動しました
Loading /Users/bar/.eggrc-wnn7...

-1

32

-1

34

Loading /Users/bar/.eggrc-wnn7...done

;; 64bit Emacsでbackend timeoutの場合
Wnn: connecting to jserver at foo.rfc2606.invalid.jp(22273)...done
ホスト foo.rfc2606.invalid.jp の Wnn を起動しました
Loading /Users/bar/.eggrc-wnn7...

4294967295

4294967295

もしかして変数のbit幅の問題?

32bit Emacsでは-1を取り、64bit Emacsでは4294967295を取る。これを16進数に直すと興味深い値が出てきます。

;; 32bit Emacs場合
(format "%x" -1)
1fffffff

(format "%x" 4294967295)
1fffffff

;; 64bit Emacs場合
(format "%x" -1)
3fffffffffffffff

(format "%x" 4294967295)
ffffffff

え〜っ!? 32bit Emacsの変数のbit幅って、29bitだったんですか! 長年Emacsを使用していたけれどしらなかった。しかも64bit Emacsは62bit? なんでこんなに中途半端なbit数なんでしょうね

上記の結果より処理結果が536870911(#x1fffffff)以上の値をとると32bit Emacsと64bit Emacsで評価内容が変わってしまう事がわかりました。

comm-unpack関数って何しているの?

次に、32bitと64bitで異なった値を返してくるcomm-unpack関数を調べてみました。comm-unpack自体は引数の値によって適切な関数を呼び出すディスパッチ処理を行い、呼び出した関数の値を返すだけの簡単な仕事しかしていませんでした。

(comm-unpack (u) result)のように引数に"u"をつけるとcomm-unpack-u32関数が呼ばれます。

comm-unpack-u32関数って何しているの?

EmacsはJServerと直接通信をしてコマンド/レスポンスのやりとりをしている訳ですが、受信したデータは*Wnn7*バッファに入ってきます。

Wnn7 バッファ

これを適切なbit長で読み出してコマンドを再構築するのが、comm-unpack関数で受信したレスポンスを32bitにアンパックしてする場合にcomm-unpack-u32関数が呼ばれます。

(defun comm-unpack-u32 ()
  (progn
    (comm-require-process-output 4)
    (+ (lsh (comm-following+forward-char) 24)
       (lsh (comm-following+forward-char) 16)
       (lsh (comm-following+forward-char) 8)
       (comm-following+forward-char))))

この時に、0xffffffffというデータを受信していると32bit Emacsと64bit Emacsで結果が変わってしまいます。

では、どんな値が*Wnn7*バッファ入ってきているのでしょう?ダンプしてみました

Wnn7 バッファ

はい、見事に0xffffffffを受信しています。ありがとうございました。

原因

  1. 32bit Emacsの整数bit幅は29bit
  2. 62bit Emacsの整数bit幅は62bit
  3. jserverから0xffffffffを受信すると
  4. 32bit Emacsは-1と評価する。
  5. 62bit Emacsは4294967295と評価する。
  6. 62bit Emacsの場合、不明なレスポンスしかこないので、backend timeoutで落ちる。

対策

原因が判明したので、comm-unpack-u32関数を修正して整数が29bit幅の以外の時は、変数の値を62bit幅に拡張する処理を入れてあげればよいと思われる。整数のbit幅が他の値をとることはあるのかな?考えないことにしておく。

wnn7egg-edep.el

Emacsの依存性があるコードはここに書かれるようなので、下記のコードを追加

(defconst interger_width_29bit (logxor (lsh (lsh 1 29) -29) 1))

interger_width_29bitは整数が29bit幅ならば1、29bit幅以上ならば0を取ります。

wnn7egg-com.el

comm-unpack-u32関数を下記のように修正。

(defun comm-unpack-u32 ()
  (progn
    (comm-require-process-output 4)
    (if (= interger_width_29bit 1)
        (+ (lsh (comm-following+forward-char) 24)
           (lsh (comm-following+forward-char) 16)
           (lsh (comm-following+forward-char) 8)
           (comm-following+forward-char))
      ;; for 62bit width
      (ash (lsh (+ (lsh (comm-following+forward-char) 24)
                   (lsh (comm-following+forward-char) 16)
                   (lsh (comm-following+forward-char) 8)
                   (comm-following+forward-char)) 30) -30))))

変数の値が62bit幅の場合は、31bit目のデータを符号ビットの場所までシフトしてから、算出シフトで元の位置まで戻してあげます。(ソースでは30bitシフトしていますが、33bitシフトの方がよいかもしれません。)

ソースとパッチ

ソースとパッチをおいておきます。ご自由にお使いください。

  1. wnn7egg-edep.el
  2. wnn7egg-com.el
  3. wnn7-egg-backend-timeout.patch

2011年6月20日月曜日

MacPortsを再インストール

古くなったMacPortsを再インストールという記事をみて、自分の環境も汚くなりつつあり整理しないといけないと思っていたので、再インストールしてみた。

MacPorts削除の前準備

MacPorts削除する前にDBのダンプやデーモンの停止をしておきます。最初にDBのダンプをとります。

# /opt/local/lib/postgresql/bin/pg_dumpall > /tmp/pgsql.dump
# /opt/local/bin/mysqldump5 -u root -x --all-databases > /tmp/mysql.dump
#

次にMacPortsでインストールしたデーモンのプロセスを停止させます。

# port unload apache2
# port unload postgresql90-server
# port unload mysql5-server
#

インストール時期がかなり前だと、どのデーモンをMacPortsでインストールしたか忘れてしまうこともあります。そんな時は、launchctl コマンドを使えば、 現在動いているデーモンからMacPortsでインストールしたものを抽出できます。

# launchctl list | grep macports
60083 - org.macports.postgresql90-server
59969 - org.macports.mysql5
59934 - org.macports.apache2
#

MacPortsを削除とインストール etc..

元記事と大体一緒なので簡単に..
一応最初に "port installed > /tmp/install.txt"として、現在インストールされているport一覧を取っておきます。

# port installed > /tmp/install.txt
# port deactivate active
# port -f uninstall installed
# port clean all
# sudo mv /opt/local /opt/local.old
#

macportをインストールして、最新版に更新。

# port selfupdate
# port upgrade outdated
#

macports.confの編集

最新版に更新後、/opt/local/etc/macports/macports.conf を編集してportarchivemodeをyesにします。これによって、コンパイル時にパッケージ アーカイブファイルが/opt/local/var/macports/packagesに作られます。またインストールする際にパッケージがあれば、再コンパイルせずにそのパッケージが使われるので、時間と電力の節約になります。

# vi macports.conf
portarchivemode         yes

sourceとpackageの移動

既にあるソースとパッケージは再利用したいので、新しいディレクトリに移動させます。

# mv /opt/local.old/var/macports/distfiles/* /opt/local/var/macports/distfiles/
# mv /opt/local.old/var/macports/packages/darwin /opt/local/var/macports/packages/
# 

インストール

パッケージが既にあるportをインストールすると、コンパイルせずにパッケージファイルを使用するので、面白いほどサクサクインストールが進みます。もちろんパッケージよりインストールするポートのバージョンが新しければ、コンパイルが行われ新しいパッケージが作成されます。

# port install lv +lesslikeslash
--->  Computing dependencies for lv
--->  Dependencies to be installed: ncurses ncursesw
--->  Unpacking tgz archive for ncursesw 5.8_0
--->  Installing ncursesw @5.8_0
--->  Activating ncursesw @5.8_0
--->  Cleaning ncursesw
--->  Unpacking tgz archive for ncurses 5.9_0
--->  Installing ncurses @5.9_0
--->  Activating ncurses @5.9_0
--->  Cleaning ncurses
--->  Unpacking tgz archive for lv 4.51_2+lesslikeslash
--->  Installing lv @4.51_2+lesslikeslash
--->  Activating lv @4.51_2+lesslikeslash
--->  Cleaning lv
#

mysqlのインストール

# port install mysql5 mysql5-server
# sudo -u _mysql mysql_install_db5
# cp /opt/local.old/etc/mysql5/my.cnf /opt/local/etc/mysql5/my.cnf
# port unload mysql5-server
# port load mysql5-server
# mysql5 -u root -p < /tmp/mysql.dump
#

postgresqlのインストール

# port install postgresql90 postgresql90-server
# mkdir -p /opt/local/var/db/postgresql/defaultdb
# chown -R postgres:postgres /opt/local/var/db/postgresql/defaultdb
# ln -s /opt/local/var/db/postgresql /opt/local/var/db/postgresql90
# ln -s /opt/local/lib/postgresql90 /opt/local/lib/postgresql
# su postgres -c ‘/opt/local/lib/postgresql90/bin/initdb -D /opt/local/var/db/postgresql90/defaultdb -E UTF8 --no-locale'
# vi /etc/sysctl.conf
kern.sysv.shmmax=167772160 
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.sysv.shmall=65536
# port load postgresql90-server
# su postgres
$ psql -f /tmp/pgsql.dump template1
$

apacheのインストール

# port install apache2 +preforkmpm
# port install php5 +apache2 +pear
# port install php5-curl php5-mbstring php5-mysql php5-postgresql
# port install php5-gd +t1lib
# mv /opt/local/apache2/conf /opt/local/apache2/conf.org
# ln -s /var/www/conf /opt/local/apache2/conf
# cp /opt/local/apache2/conf.org/extra/mod_php.conf /opt/local/apache2/conf/extra/
# cp /opt/local/apache2/conf.org/mime.types /opt/local/apache2/conf/
# rm -r /opt/local/apache2/htdocs
# ln -s /Library/WebServer/Documents /opt/local/apache2/htdocs
# ln -s /var/www/conf/php/php.ini /opt/local/etc/php5/php.ini
# 
# port load apache2
#

それ以外のportも、最初に保存したinstall.txtを見ながら、抜けがないようにインストールしていきます。

他のマシンもMacPortsを再インストール

MacBook air 11インチにもMacPortsが入っているので、同じようにして再インストールしていきます。

ただしpackageファイルは先ほど再インストールが終了したマシンから移し替えます。このようにすれば、MacBook airには最新のパッケージが入るので、コンパイルレスでインストールができます。実際、実行すると爆速でインストールが終了します。