Ubuntu11.10で JSPカーネルの cfg が動かない件およびその暫定対策
背景
学校関係からいくつかホップして,TOPPERS の cfg が動かないので何とかして,という問い合わせがあった.
もう少し細かくいうと,Ubuntu11.10 で nxtJSP が動かないという.
そりゃそうですわ Android を始めとしてあちこちのソースコードリポジトリで問題が勃発した地雷バージョンですもの.新しいものを使えば安全という甘い幻想を持つのは若者の特権だから,大いに爆死すればよい. そう思ってしばらく放置していた.
「キホン,動作推奨環境以外で動かないときは自己責任で解決する」ということを教えるのが学校の大きな役割だし,解決への戦術を教えるのが学校の教職員の存在意義のはず.そのうち周りの大人達が助言をしながら,きっと解決するでしょう,と.
そもそも,困っている人が困っていない人の手を動かすときは,インセンティブが要る.これは人間社会のキホン.典型的には金で,時には社会学的欲求の充足で代償するわけだけれども.
なんにせよ本件では,私は全然困っていない.インセンティブもない.
だがしかし.
そうこうしているうちに,なんだか私のメアドを含むCCがいっぱいついたメールが飛んでくるようになった.まあ,困っているのは解った.でも困っていない私にCCするのやめてくれないかな….
というわけで,インセンティブができた.解決すれば CC やめてくれますよねっ♪(きらきら)
なんかすごく後ろ向きなインセンティブだけれども.
ついでに,やったことを書いておく.別段難しいことをしたわけではない.けれども,まあ,最近は LL な言語でアジャイルな開発が流行りで,ポータブルなバイナリを作るという意識も持つ機会がないかもしれないという気もする.便利になった反面,最近の若者にとっては,学ぶ機会が減って可哀想かもしれないなぁ.
やったこと.時系列
現象確認
まず,Ubuntu11.10 の環境作成.VMware のインスタンス立ててインストールして…とか,手間がウザすぎるので,EC2で適当なAMIイメージを見つけてサクっと立ち上げる.JSP カーネルのソースコードアーカイブをダウンロードして,展開.cfg の作成. configure で環境を作って…そうか cfg に食わせるソースコードの生成にはクロスコンパイラが要るのか…
でもクロスコンパイラのビルドをする気力もないので,まずは,ホストの gcc で代用する.
なるほど確かにハングアップする.無限ループに入っている風味.報告どおり.
Ubuntu10.04.3 LTS で再現性確認
10.04については,Android のイメージビルド用に EC2インスタンスを持っていたので,ちゃちゃっと立ち上がる.
JSP-1.4.4 のリリース時には Ubuntu10.04.3 LTS を使ったはず.そのため,最初の問い合わせに対しては「10.04 を使っています」と返しておいた.それでもなお解決していないとなると,もしかしたら 10.04 でも動かないのかもしれない.
ライブラリの更新などで 10.04.3 でも動かなくなっていたら,申し訳ないことしたなぁ…と思いながら Ubuntu11.10 で行った通りの手順で cfg を実行したら…
無事動いたよ.(´・ω・`)
ということは,推奨動作環境を一切無視していますね.無視られた上に困った困った言うリクエストに,応える価値があるのかどうかブルーになりつつ,続ける.
本当は,この時点で解決できるのだけど,少し寄り道してみる.
動作するバイナリを用いた不動作環境での確認
cfg は g++ で記述されている.g++ …というか C++ というか…は至近数年で大きく変革した.そのため,前世紀に記述された cfg が動かなくなるのは,もはや時間の問題ではあった.cfg 自身がC++の本流的な設計とはちょっと違う感じなので,なおさらのこと.さて,今回の不具合の根っこはどこにあるだろうか.これをざっくり知っておきたい.(←寄り道)
10.04.3 上では,動作するバイナリができた.これを 11.10 で動作するかを確認する.これで,コンパイラとアプリケーションの相性なのか,アプリケーションとライブラリの相性なのかが,概ね分かる.ABI が変更になっている場合なども動かなかったりするので,クリスプに切り分けができるわけではない.とはいえ,分からないことだらけのときは,切り分けの役に立ちそうなパラメータはすべて試してみることが大事.
11.10では,10.04.3 上で動作していたバイナリも,11.10 と同様の挙動を示した.つまり,不具合の原因はコンパイラではなく,ライブラリ側に主要因がありそうということが想像できる.
解法 : スタティックリンク
10.04.3 でスタティックリンクのバイナリを作る.バイナリのリンク時に,gcc に -static オプションを付けるだけ.バイナリのサイズは増えるけれども,やむかたない.
このバイナリを 11.10 上にコピーして確認した.
動作良好.(`・ω・´)
[osx][git] OSX 版 git で git-xxx コマンドを呼ぶ方法
便利かも。
便利かも.
…と思ったのだけれど,git-osx-installer の 1.7.8.3 辺りでやってみたら呼んでくれなかった.
各地ブログをナナメ読みするとみんなできているようなのになぁ,と思いながら調べていったら,判った.
export GIT_EXEC_PATH=~/bin
などする必要がある.git の仕様が変わったのか,ディストリビューションに依存するのか,理由は不明.
さっそく,遊んでみた.
bitbucket を最近使い出したのだけれど,clone のパスをいつも忘れる.
対策として,こんなもの (git-bitbacket)を書きなぐってみた.
リポジトリの生成は WebAPI が公開されているので curl 使ってイケるはずなのだけれど,その辺は,追々.
#!/bin/bash USERNAME=monaka if [ $# -ne 2 ] ; then echo "git-bitbucket cmd repository-name" 1>&2 exit 1 fi case $1 in clone) cmd="clone git@bitbucket.org:$USERNAME/$2" ;; esac eval git $cmd
NDKをリビルドする.
kernel.org クラック事件の余波で,現在のところ真っ当にリビルドできない模様.(あとで書く)
文字列を考慮した数値演算処理分岐
CSVでWordPressにデータを流し込み、ランプ名のキーワードでAPIかけて画像とかブログとか楽天の情報を引っ張ってくるんだけど、CSVの標準価格に”オープン”といれると、実際のコンテンツには、”標準価格 0円”と表示されてしまうことが判明。これって、税抜きの値段に消費税の5%をかけて表示させているんだけど、”オープン”といれると書式が文字列になって、それにかけ算するものだから0になってしまうらしい。
こうすると若干ではあるもののスッキリするような気がPHP素人の私にはする.なんとなく + 0 以外にも軽量な数値変換手段がある気がするし,もっと効率の良い方法があるような気もする.数値型と文字列型の変換コストがよく判っていないもので.
<?php $listPrice = "1"; $listPrice = "オープン"; if ((string)($listPrice + 0) === $listPrice) { echo $listPrice * 1.05; } else { echo "オープン"; } ?>
仕組み
加算演算子では,オペランドに float が含まれるとき以外は結果が整数となると仕様にある.
よって,$listPrice + 0 の結果は,$listPrice が "オープン"のとき整数型の 0,"1"のとき整数型の 1 となる.その結果をstring で強制的に型変換するので,結果は "0" または "1".
=== 演算子は事前の型変換を行わない比較なので,文字列が数値表記であってもそのまま比較.
$listPrice = "オープン"のときは ("0" === "オープン") なので結果は false.$listPrice = "1" のときは,("1" === "1")となるので,true.
浮動小数点数についても,問題なく動く.$listPrice が浮動小数点数に変換され,+演算子の結果も浮動小数点になる.
よくわかんないこと
このコード,手元のOSX付属の5.3.6では,下記のように替えても動いてしまう.
if ((string)($listPrice + 0) == $listPrice) {
== は,型の相互変換を行う.左辺は数値形式の文字が含まれることが自明.マニュアルの比較演算子の項を見ると,数値が文字列に変換されるはずなのだが.
まあもっとも,同マニュアルの== による緩やかな比較表を見ると,期待されている挙動らしい.
わけわからん.
結論
型周りでこの手の落とし穴が山盛りなので,PHPはニガテ.仕事では絶対に使いたくない….
オチ
ブツクサ言いながら,久しぶりにマニュアル読んでいたら,is_numeric ってのがあるじゃないの… orz.
でも書いちゃったから残しておく.
Emacsを22系(Carbon)から23系(Cocoa)へ乗り換え.
長い間,dmg 形式で配布されているCarbonEmacsを使っていたのだけれど,いつの頃からか置換などすると妙に遅いと感じるようになった.気のせいなのか,私がなんらかしでかしたのかは不明.
テキストエディタで反応が遅いのはストレス溜まる.AppleはアプリのCocoa化を推奨しているようだし,本家Emacsも23系からCocoaに移ったということで,乗り換えた.
ビルド
inline_patch-23.2-beta3.tar.gz と emacs-23.2a.tar.gz を引っ張ってきて展開してパッチ当てて configure して make bootstrap して make install.
Snow Leopard だと,Fink とか MacPorts とか使わんでも,Apple純正の状態でもビルドできるっぽい.Lion のことは判らない.
環境の上書き
Snow Leopard には,/usr/bin/emacs-21.2.1 という,いったいいつのだよ,という emacs が入っている.
こいつが呼び出されないよう, ~/.profile に細工する.
alias emacsclient='/Applications/Emacs.app/Contents/MacOS/bin/emacsclient' alias emacs='open /Applications/Emacs.app'
ssh か何かで入った時には emacs がトチ狂いような気がするけれど,そのときは手動で unalias するからいいや.
--daemon を使わずに emacsclient を使う
Emacs 23系は,emacsclient を使うときに幸せになれるよう, --daemon オプションが追加になっている.
デフォルトのフォントでも気にならない人は,ログイン時にでも --daemon オプションで起動すればよいはず.
しかし,フォントを変えるよう init.el にゴニョゴニョしている人は,「error: Fontset `tty' does not exist」などいうエラーを喰らう.
ぐぐったところ,「(set-fontset-font)の前に(display-graphic-p) で判別するとエラーにならないよ」ということのよう.実際エラーは取れるのだけれど,emacsclient で起動したフレームにはデフォルトのフォントしか出てこない.
そこで,--daemon を使わない方法を考えた結果,バッドノウハウが一つ浮かんだ.
まず,.profile に下記の行を加えておく.
export ALTERNATE_EDITOR=~/bin/emacs.sh
この環境変数は,emacsclient が emacs を探せなかったときに呼び出すエディタを指定するためにある.これを使ってちょっとしたトリックを行う.
~/bin/emacs.sh は,下記のようにしておく.
#!/bin/sh open -a Emacs.app sleep 1 /Applications/Emacs.app/Contents/MacOS/bin/emacsclient $*
open コマンドは,起動をかけると直ぐに終了してしまうので,1秒のスリープを入れてある.1秒以内にEmacs が起動しない場合でも,次に実行される emacsclient が再び ~/bin/emacs.sh を呼び出すので,正常系では数秒以内に emacsclient の処理は成功する*1.
これも,ssh などでログインして GUI の無い状態で作業すると破綻する.判別の方法があればよいのだけれど.
JSPカーネルにサブセットは必要か
TOPPERS界隈の最近の流行りは,壊れた日本語や長文で思いの丈で語ることらしいです.私が叩き上げられていた頃は,OSS の ML で patch 添付しないでメールを送信するのは無能を表明するようなものだくらいに嗜められたように思うのですが.
恥の概念は時代の変遷により変わりますからね.トシ取りました.まだ不惑ですけれど.
で,一般論として長文での思いの丈は概ねいくつかのテンプレートに分解できます.そのなかで典型なのは「初心者に優しいサブセット提供」です.今回も出ていました.
まあ,何か解決したいっていう気持ちは判りますけれどね. μITRON4.0仕様スタンダードプロファイルに関して言えば,殆ど作る意義ないのですよ.
確かに仕様書に膨大な通信機能のAPIがあります.ですが,それらの相互依存はスタンダードプロファイル範囲では存在しません*1.使わないものは単に無視すればいいだけです.
セマフォだけしか使わないと決めればよいだけ.実際,組込みソフトウェア技術者を極めるための本をたくさん書いていてセミナーの壇上で見かけるような方々でも,控室では「開発ではセマフォくらいしか使わない」と談笑していたりします.それでよいのですよ.カーネル屋は実装するために仕様のすべてを頭に叩き込まねばなりませんが,アプリ屋さんがカーネル屋を真似する必要はありません.
POSIX系OSやWindowsで全てのサービスコールとライブラリを覚えている人は稀です.開発者は自分が使う定石を持っていて,そのなかでアプリを作ります.
これとμITRONのサービスコールの利活用は同じ構図のはずなのですが,丸暗記できそうなくらいに μITRON4.0 仕様が簡素なので,なにか誤解が生じてしまうの…かな?
などなどつらつらと考えると,JSPカーネルのコードをちまちまと弄ってもユーザは満足には到らず,デザインパターンやイディオムの欠如を補って頂く方向での努力をしたほうがよいのではないかという結論に,ワタクシ的には至ったりします.
ちなみに
「いやいや,カーネルのサイズを小さくしたくて」が云々言うのもテンプレの一つですが,これも JSPのサブセットで解決するのはスジが悪いです.
開発環境に制約がある場合を除き,JSPは libkernel.a を使おうという設計になっています.そのため,アプリがセマフォしか使っていなければセマフォしかリンクされません.制約がある場合でも semaphore.c だけリンクするようにビルド定義を替えるだけの話でしかないはず.
これはカーネルの問題というよりは,ビルド定義をどうするかという,アプリ領域の問題でしょう.
サイズを小さくしたい場合,一番ネックになるのはタスクに割り当てるスタックサイズです.μITRON4.0の自動車プロファイルのように,制約タスクを入れたり待ちを無くしたりと,抜本的な対策が必要になります.
JSPを小手先だけ弄くって解決するものではありません.本気で省メモリに挑むなら,ASPに対するSSPのような,別物を作るくらいの覚悟が要るでしょうねぇ.
というわけで
「JSPのサブセットを作れば皆使うよ」という主張には「何となく簡単になった気がする,という程度の満足しか得られませんよ」,という反論で応じたい.というお話でした.
MLに書くには長過ぎるので,日記に落としておく次第.