どこまでがスレッドセーフなのだろうか

Firefox3からThread機能が使えるようになったと、よろこんで使い倒していますが、なんか微妙な雲行き。


Threadの動作を知るために自分でビルドしたFirefox3を使ってみました。
エラーがぼりぼり出ますが、問題のあるところは逐一メッセージがでますので、あやういプログラムのチェックには有用ではないかと思います。
# まぁそもそもFirefox3を起動する時点で、ものすごいエラーが出るんですが。


で。Threadを利用したコード(前回かいたThreadPoolでおちまくるプログラム) を動かしてみると、

!!!!! XPConnect wrapper thread use error...
Main Thread Only wrapper accessed on another thread
・・・(ry

というメッセージが大量にでました。
dump()ですら、スレッドセーフでないようで。
スレッドセーフかどうかリファレンスに書いてあればいいんだけど。


まだ、Threadは使うべきではないのかもしれない。

nsIThreadPoolの使い方

今回も、Firefox拡張機能開発のお話。


Firefox3からThread関係のインターフェースが追加されています。
ネットワークの通信処理をかいているのですが、nsIAsyncInputStreamやnsIAsyncOPenStreamの、AsyncWait()の使い方がわからないので、ベーシックな感じでThreadで処理しています。
# AsyncWait()を使う場合, nsIBinaryInputStreamって使っていいのかな。


基本的なThreadの処理はMDCにあるサンプルコードを見ればわかります。
しかし、処理ごとにThreadを作っていると、Thread管理するためのコードが必要になったり、Thread数が爆発してしまったりします。


さて、XULPlanetのXPCOMの項目にThread関係があります。

nsIThread
nsIThreadEventFilter
nsIThreadInternal
nsIThreadJSContextStack
nsIThreadManager
nsIThreadObserver
nsIThreadPool

http://www.xulplanet.com/references/xpcomref/group_XPCOM.html

ここを見ると、nsIThreadPoolというインターフェースがあるのがわかると思います。
ThreadPoolでは、あらかじめいくつかのThreadを用意しておき、処理が割り当てられると用意しているThreadをその処理に割り当てます。
また、一定以上の処理の割り当てによって、用意しているThreadが足りなくなると、処理中のThreadがあくまで処理を待機します。
この機能によって、Threadを使った処理のキューイングのようなことができ、また、簡単に並列に実行する処理数を変更することもできます。
nsIServerSocketを使うときとか、かなり便利です。(てか、それを使うために調べたんですが)


では、使い方をサンプルコードにて。

// XPCOMUtilsオブジェクトをロード
// XPCOMUtils.generateQI を利用すると、 QueryInterfaceを簡単に記述可能
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

// nsIThreadManagerサービスを取得
var ThreadManager = Components.classes["@mozilla.org/thread-manager;1"].getService();

// thread pool を動作させるためのスレッドを用意
//var thread = ThreadManager.newThread(0);

// thread pool を作成
var threadPool = Components.classes["@mozilla.org/thread-pool;1"].createInstance(Components.interfaces.nsIThreadPool);

// thread で処理したいお仕事
var work = function(id) {
  this.workId = id;
}
work.prototype = {
  run: function() { dump("お仕事" + this.workId + "\n"); },
  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIRunnable])
}

// thread に thread pool を割り当て
//thread.dispatch(threadPool, thread.DISPATCH_NORMAL);

// お仕事を thread pool に割り当て
threadPool.dispatch(new work(1), threadPool.DISPATCH_NORMAL);
threadPool.dispatch(new work(2), threadPool.DISPATCH_NORMAL);
threadPool.dispatch(new work(3), threadPool.DISPATCH_NORMAL);
threadPool.dispatch(new work(4), threadPool.DISPATCH_NORMAL);

といった感じ。


nsIThreadPoolは nsIRunnable を実装しているので、thread.dispatch() に渡してやることで、threadPool の処理をバックグラウンドで実行を開始します。
訂正: nsIThreadPool用にThreadを用意しなくてもdispatchで処理を割り当てると呼び出しThreadをブロックすることなく実行してくれるみたいです。
あとは、threadPool.dispatch() に、通常のThread処理と同じように nsIRunnableインターフェースを実装したオブジェクトを渡してあげると、threadPoolが割り当てられた処理をさらに別スレッドで動かしてくれます。


thread poolのthread数の調整ですが、

Properties

PRUint32 idleThreadLimit
Get/set the maximum number of idle threads kept alive.
PRUint32 idleThreadTimeout
Get/set the amount of time in milliseconds before an idle thread is destroyed.
PRUint32 threadLimit
Get/set the maximum number of threads allowed at one time in this pool.

http://www.xulplanet.com/references/xpcomref/ifaces/nsIThreadPool.html

と、プロパティがあります。 threadLimit が処理を行う最大スレッド数です。これを増減すれば同時に処理するスレッド数が変わると思います。
が、未確認です。


なぜ未確認か。それは、ThreadPoolを利用する処理を組み込み、ThreadPoolのすべての処理が終了すると、Firefoxがおちるという症状が発生しています。
状況整理もかねて、このエントリを書いています。
原因が上記のコードに含まれている場合はあとで修正します。


追記:
とりあえず、単純な処理でThreadPoolを使う上ではFirefoxがクラッシュするということはありませんでした。


今、書いているコードでクラッシュするのは通信処理との兼ね合いのよう。
nsISocketTransportは、nsITransportを継承していて、nsITransportは nsIStreamTransportService から生成されます。そして、nsIStreamTransportService内部ではnsIThreadPoolを使っています。
nsISocketTransportがどう生成されるのか次第ですが、nsIStreamTransportServiceと競合してるような・・・そんな気が。
もっと詳しく調べてみます・・・.

拡張機能開発: nsIThreadManager利用時における定義済みコアオブジェクトの挙動

Firefox拡張機能を相変わらず作っております。
スレッドではまったのでメモ。


時間がかかる処理を行うので、Firefox3から導入されたnsIThreadManagerを利用して、マルチスレッディングで楽しようとコーディング。

MDC: The Thread Manager
https://developer.mozilla.org/ja/The_Thread_Manager

本家のサンプルのほぼそのまんまです。


で、です。
スレッド処理に切り替える前、デバッグ出力する際に、String(obj) として文字列に変換してやっていました。objがnullな可能性もあったので。

var obj = null;
dump("obj=" + String(obj));    // ここで停止

そして、スレッドで処理するように書き換えた後、このコードを実行してみると、そこでプログラムが停止。Firefoxすら反応しなくなる。
原因が、よく分からないながら、String()を外すと動き出す。


同様に、

var x = Math.ceil( xxxx/ yyyy);

な感じの処理をおこなっている場所でも、停止。


どーやら、スレッド内で、デフォルトで用意されている「定義済みコアオブジェクト」というものに触れると停止するよう。

註: DOM はスレッドセーフではないので、バックグラウンドスレッドから DOM や ユーザーインタフェースにアクセスしてはいけません。クラッシュの原因となります。


MDCのページのこの1文がすごく気になる。
まさか、 「定義済みコアオブジェクト」はスレッドセーフではない? とか?
ソースでも読んで確認してみたほうがいいのかしら・・・。

PS3にFedora9をインストール

PS3を買ったので、Fedora9をインストールしてみました。
適当にメモ。

基本、

http://cell.fixstars.com/ps3linux/index.php/PS3_Linux%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

を参考に。
あと、Fedora9 のPPC インストールノートも。 PlayStation3 の項目。

http://docs.fedoraproject.org/release-notes/f9/ja/sn-ArchSpecific.html#sn-ArchSpecific-ppc-install


0.準備
・Fedora9 for ppc のディスクイメージをダウンロード。
・USBマウス、USBキーボードを接続。


1.HDDをフォーマット。 「ほかのシステムに10G割り当てる」を選択。
サイズが自由に決められないのは不便。 せっかく80Gもあるんだから、自由に設定させてほしい。


2.ブートローダをインストール。 kbootを入れました。
ftp://ftp.kernel.org/pub/linux/kernel/people/geoff/cell/ps3-kboot/kboot-20080609.bld を、
USBメモリに /PS3/otheros/otheros.bld としてを保存し、ブートローダをインストール。
有線起動OSをほかのシステムに変更。
Fedoraのディスクを入れ再起動。


3.Fedoraインストーラを起動。
再起動すると、 Linuxらしきものが起動し、

kboot:

で停止。linux64 video=720p と入力し起動。
あとはFedora9のインストールとほぼ一緒。

気になったこと:
・途中、「HDD(ps3da) をフォーマットしますか?」的なメッセージがでたが、YESで問題なかった。PS3のGameOS領域は隠されているみたい。
・フルインストールすると10GBぐらい必要らしい。とりあえず必要最低限に削ってインストールする方がいいらしい。
・また、どこかのサイトによるとrootのパスワード入力時、デフォルトでCapsLockが入ってるとのこと。本当にそうだった。
・インストール完了後時間が9時間ずれてた。システム時間をUTCとして設定していいようだ。


インストールが完了するまで、1時間ちょっとぐらいかったかな。
インストールが終わったら、ディスクが出てくる。
# それまでXBox360でゲームしてました。テイルズ。


4.Fedora9 起動
「kboot:」のプロンプトをしばらく放置すると自動で起動するよう。
初期設定が終わって、GUIでログイン。
ちなみに、PS3のOSに戻すときは、kbootで game と入力する。


これで完了・・・と思いきや、起動していく途中でフリーズ状態に・・・
Ctrl+Alt+BackspaceでXを落として、とりあえずコンソールへ。
メモリが圧迫されてこんな状況なのかとおもったらスワップが認識されてない。
インストール時に、LVMを使わず、すべてベーシックパーティションで設定したせい?


まず、

swapon -a

スワップをマウントするか試す。・・・ダメ。


/etc/fstab のswapの設定を確認。

LABEL=SWAP-ps3da2 swap ・・・

って、かいてある。

swapon -L SWAP-ps3da2

ラベルが認識してない。


swapを作り直して、もう一度チャレンジ

mkswap -L SWAP-ps3da2 /dev/ps3da2

swapon -a、 swapon -L SWAP-ps3da2 どちらもだめ。
mkswap したときに UUID も作ってくれたので、 swapon -U も試してみたがダメ。


直接デバイス指定。

swapon /dev/ps3da2

マウントした。
めんどくさいので、fstab も直接指定に変更。swapon -a でマウントする。


GUIに切り替えてログインしてみると、問題なくGnomeが起動。でも重い。
メモリの空き1MBぐらい。スワップ, 120〜170MBほど使用している。


システムのアップデートも無事終了。
次はCELLプログラミングの環境を整えて, 勉強するかなー

今更Windows Vistaを購入

先週、今更ながらWindows XPからVista(Ultimate)に乗り換えました。


来年〜再来年にWindows7も控えてるこの状況で乗り換えた理由は、
 ・XPの青くて丸っこいデザインにあきあきしたこと
 ・XPがやたらとフリーズするということ(おそらくデバイスドライバ起因)
後者は、単にOSが腐ってただけだと思いつつ。


一部対応していなさげなデバイスがあったので、64bitは見送り、32bit版を購入。
できれば64bit版もつかってみたいですが。


Vistaを使ってみて、
UACは速攻無効化
・パフォーマンステストで一番スコアが低いのはCPU(E6750)。
・メモリ食いすぎ(起動時50%=1GB)
・でもほとんどシステムキャッシュなのか重くならない
サウンドオンボード)のドライバが微妙なのかノイズ乗りまくり
Firefoxや一部のアプリが落ちまくる
・スリープから復帰すると、たまにExplorerが死ぬ
・やっぱりOSがたまにフリーズする。(原因はメモリだと診断される)
・でもメモリテストは正常


とまぁ、OSを変えて、余計に症状が悪化したうちの自作PCです。
どうも本気でマザーボードASUS P5K-E)が腐ってるらしい。
これは買い換えフラグか・・・ でも、PS3予約したのでお金ありませんorz


それはともかく、はじめてVistaをまじめにつかってますが、基本的にXPとなんも変わらない気がします。
# SP1の前はひどかったのかもしれませんが。
若干の操作方法と見た目が違うだけですね。
これがだめなら、Linuxマシンは使えないんじゃないかと・・・。(もちろんMacも)


バグまみれとかいう悪評についてはまだなんともいえません。
物理的におかしいっぽいPCなので。
まぁWebDAVが使えないのはつらいですが。

SEOスパムメール

今朝、会社でメール確認すると「SEO業者」から「未承諾広告」っていう名のSPAMが届いてました。


メールには「SEO対策で新規顧客開拓を!」 みたいなことが書いてあります。


うちの会社のHPをみてメールしたそうです。
HPには、Web制作とか、SEOしますとか書いてあるにも関わらず。

業務をみたら、普通競合他社ってヤツになるだろうと思わないだろうか。

考えられること:
・HPなんてそもそもみてない
・そこまでみてない(それ以外の業務もあるので)
・いわゆる、「その域に達していない」状態 (Web制作全般において)

・・・全部に当てはまりそうですが。

そもそも「SEO対策をするべき軸」がうちの会社にはないのでするだけムダなわけですが。



ひさしぶりに更新する内容がネガティブまっしぐらです。
Firefox拡張機能開発について、メモろうとおもいつつ未だに書いてません。

拡張機能開発のメモ(開発を始めるまで)

拡張機能を開発することになったので最初にすべきことをメモっておきます。
開発をはじめるまでの学習手順(?)がメインです。
開発方法についてはリンク先を参照してください。


Mozilla Developer Center(MDC)の拡張機能のページに基本的な情報はそろっています。

http://developer.mozilla.org/ja/Extensions

開発環境

  • Firefoxをそのまま開発環境として利用
    • プロファイルを開発環境用に分けることで、通常利用してる場合でも設定などへの影響はない
    • Thunderbirdの拡張開発もベース技術は同じ
  • 開発言語はJavascriptがメイン
  • ブラウザに機能を組み込んだりウィンドウなどを表示させるためにXULと呼ばれるXMLベースのマークアップ言語を使用
  • ファイル操作やブラウザ機能など、Javascriptでは実現できない機能はXPCOMを利用
    • 独自のXPCOMC/C++言語で開発可能。用意されていない機能を追加可能
    • XPCOMから既存のXPCOMの呼び出しも可能
    • XPCOMを開発するにはGecko SDKが必要(MDCからダウンロード)

開発を始める前に

ブラウザの設定

次のページの通りに設定。

Setting up extension development environment
http://developer.mozilla.org/ja/Setting_up_extension_development_environment

また、Console2やChrome List、DOM Inspectorなどの拡張機能はインストールしておくと非常に便利。

学習

次の知識が必要


次のMDCのチュートリアルを読む。


また、次のサイトも役に立つと思います。


とりあえず、ここまでが開発を始めるまでの下準備です。
自分はまだXULの勉強中です・・・。