この問題に関心がある場合は、以下の更新 #2 をお読みください ;)
このコードを拡張機能の JS に入れたとします。
var reader = {
onInputStreamReady : function(input) {
var sin = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
sin.init(input);
sin.available();
var request = '';
while (sin.available()) {
request = request + sin.read(512);
}
console.log('Received: ' + request);
input.asyncWait(reader,0,0,null);
}
}
var listener = {
onSocketAccepted: function(serverSocket, clientSocket) {
console.log("Accepted connection on "+clientSocket.host+":"+clientSocket.port);
input = clientSocket.openInputStream(0, 0, 0).QueryInterface(Ci.nsIAsyncInputStream);
output = clientSocket.openOutputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0);
input.asyncWait(reader,0,0,null);
}
}
var serverSocket = Cc["@mozilla.org/network/server-socket;1"].
createInstance(Ci.nsIServerSocket);
serverSocket.init(-1, true, 5);
console.log("Opened socket on " + serverSocket.port);
serverSocket.asyncListen(listener);
次に、Firefox を実行し、telnet 経由でソケットに接続します
telnet localhost PORT
5 つのメッセージを送信すると印刷されますが、6 番目のメッセージを送信しようとすると、
firefox-bin: Fatal IO error 11 (Resource temporarily unavailable) on X server :0.0.
さらに悪いことに、これと同じコードを XPCOM コンポーネントに入れようとすると (そこが実際に必要なため)、telnet 経由でメッセージを送信しようとすると、
Segmentation fault
または時々
GLib-ERROR **: /build/buildd/glib2.0-2.24.1/glib/gmem.c:137: failed to allocate 32 bytes
aborting...
Aborted
Firefox を起動した端末に出力されました。
これは本当に奇妙なことです..私が貼り付けたコードに何か問題があることを見つけることができますか、それとも私のFirefox/システムに何か問題がありますか?それともnsIServerSocketインターフェースは非推奨ですか?
Firefox 3.6.6 でテストしています。
私は本当にいくつかの答えをいただければ幸いです。XPCOM コンポーネント内でソケットを使用する良い例を教えてください。私は周りでそれらの多くを見たことがありません。
アップデート
以前は機能していたことに気付いたので、コンソールコンポーネントが壊れていると思います。これがどのように関連しているのかわかりません。しかし、このコンポーネントを使用しない場合、ソケットは正常に機能しています。
これが私のコンソールコンポーネントのコードです。何が問題なのか、なぜ干渉するのかを突き止めようとします。後で調査結果を投稿します。おそらく、ここでひどく間違ったことをして、javascript でセグメンテーション違反を引き起こしている可能性があります =)
ブードゥー..
コンポーネント/Console.js:
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
Console.prototype = (function() {
var win;
var initialized = false;
var ready = false;
var _log = function(m, level, location) {
if (initialized&&ready) {
var prefix = "INFO: ";
switch (level) {
case "empty":
prefix = ""
break;
case "error":
prefix = "ERORR: "
break;
case "warning":
prefix = "WARNING: "
break;
}
win.document.getElementById(location).value =
win.document.getElementById(location).value + prefix + m + "\n";
win.focus();
} else if (initialized&&!ready) {
// Now it is time to create the timer...
var timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
// ... and to initialize it, we want to call
event.notify() ...
// ... one time after exactly ten second.
timer.initWithCallback(
{ notify: function() { log(m); } },
10,
Components.interfaces.nsITimer.TYPE_ONE_SHOT
);
} else {
init();
log(m);
}
}
var log = function(m, level) {
_log(m, level, 'debug');
}
var poly = function(m, level) {
_log(m, "empty", 'polyml');
}
var close = function() {
win.close();
}
var setReady = function() {
ready = true;
}
var init = function() {
initialized = true;
var ww = Components.classes["@mozilla.org/embedcomp/window-
watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
win = ww.openWindow(null, "chrome://polymlext/content/
console.xul",
"console", "chrome,centerscreen,
resizable=no", null);
win.onload = setReady;
return win;
}
return {
init: init,
log : log,
poly : poly,
}
}());
// turning Console Class into an XPCOM component
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
function Console() {
this.wrappedJSObject = this;
}
prototype2 = {
classDescription: "A special Console for PolyML extension",
classID: Components.ID("{483aecbc-42e7-456e-b5b3-2197ea7e1fb4}"),
contractID: "@ed.ac.uk/poly/console;1",
QueryInterface: XPCOMUtils.generateQI(),
}
//add the required XPCOM glue into the Poly class
for (attr in prototype2) {
Console.prototype[attr] = prototype2[attr];
}
var components = [Console];
function NSGetModule(compMgr, fileSpec) {
return XPCOMUtils.generateModule(components);
}
このコンポーネントを次のように使用しています。
console = Cc["@ed.ac.uk/poly/console;1"].getService().wrappedJSObject;
console.log("something");
そして、これはソケットを壊します:-S =)
更新 #2 OK、誰かがこのことをチェックすることに興味がある場合は、本当に感謝します + これはおそらく何らかのバグだと思います (javascript からの Seg 障害は発生しないはずです) 私は拡張機能の最小バージョンを作成しました問題が発生する場合は、次の場所からインストールできます。
http://dl.dropbox.com/u/645579/segfault.xpi
重要な部分は chrome/content/main.js です:
私の友人と私がエラーを再現できる方法は、Firefox を起動することです。その後、「Opened socket on 9999」という新しいウィンドウが表示されます。「telnet localhost 9999」を使用して接続し、いくつかのメッセージを送信します。2 ~ 6 件のメッセージの後、firefox が起動されたターミナルに次のいずれかが出力されます。
1 (最も一般的)
セグメンテーション違反
2 (何度も見た)
firefox-bin: X サーバー :0.0 で致命的な IO エラー 11 (リソースが一時的に利用できません) が発生しました。
3 (何度か見た)
GLib-ERROR **: /build/buildd/glib2.0-2.24.1/glib/gmem.c:137: 32 バイトの割り当てに失敗しました 中止しています...中止しました
4 (一度見た)
firefox-bin: ../../src/xcb_io.c:249: process_responses: アサーション `(((long) (dpy->last_request_read) - (long) (dpy->request)) <= 0)' が失敗しました. 中止しました
さらに情報が必要な場合、またはバグ レポートを投稿する場所を教えていただける場合:-/ 喜んで対応させていただきます。
これは多くのバグの 1 つにすぎないことはわかっていますが、これを回避するにはどうすればよいかご存知ですか? そんな私の「コンソール」を、そんな風に使っていきたいと思います。
人々が示唆しているように、バッファ/フラッシング/トライ/キャッチでやってみますが、トライ/キャッチがセグフォールトをキャッチするかどうかは疑問です...