firefox - 在 XPCOM 组件(Firefox 扩展)中使用套接字 (nsIServerSocket)(套接字 + 新窗口 = seg 错误)

标签 firefox sockets segmentation-fault firefox-addon xpcom

如果您对此问题感兴趣,请阅读下面的更新#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 接口(interface)是否已被弃用?

我正在使用 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 好吧,如果有人有兴趣检查一下这个东西,我真的会 欣赏它+我认为这可能是某种错误(段错误 来自 javascript 不应该发生) 我制作了导致问题的扩展的最小版本, 您可以从这里安装它:

http://dl.dropbox.com/u/645579/segfault.xpi

重要的部分是 chrome/content/main.js:

http://pastebin.com/zV0e73Na

我和我的 friend 重现错误的方法是启动 firefox,然后会出现一个新窗口,显示“Opened socket on 9999”。使用“telnet localhost 9999”连接并发送一些消息。 2-6 条消息后,您会在 启动 Firefox 的终端:

1(最常见)

段错误

2(看过多次)

firefox-bin:致命 IO 错误 11(资源暂时不可用) X 服务器:0.0.0.0。

3(看过几次)

GLib-错误 **:/build/buildd/glib2.0-2.24.1/glib/gmem.c:137:失败 到 分配32字节 正在中止... 已中止

4(看过一次)

firefox-bin: ../../src/xcb_io.c:249: process_responses: 断言 `(((长) (dpy->last_request_read) - (长) (dpy->request)) <= 0)' 失败的。 已中止

如果您需要更多信息或者可以告诉我在哪里发布错误 报告:-/我很乐意这样做。

我知道这只是众多错误之一......但也许您有一个 我应该采取什么不同的做法来避免这种情况?我想 以这种方式使用我的“控制台”。

我会尝试按照人们的建议使用 buffer/flushing/try/catch 来完成此操作,但我想知道 try/catch 是否会捕获 Seg 错误...

最佳答案

这是一个线程问题。回调 onInputStreamReady 恰好在不同的线程中执行,并且仅允许从主线程访问 UI/DOM。 解决方案非常简单:

改变

input.asyncWait(reader,0,0,null);

var tm = Cc["@mozilla.org/thread-manager;1"].getService();
input.asyncWait(reader,0,0,tm.mainThread);

关于firefox - 在 XPCOM 组件(Firefox 扩展)中使用套接字 (nsIServerSocket)(套接字 + 新窗口 = seg 错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3176442/

相关文章:

javascript - 从 javascript 中的字符串加载 XML 在 IE 8 中工作正常,在 Firefox 中失败

java - 当 InputStream.read(array) 不返回 array.length 时到达流的末尾?

c++ - 段错误(核心转储)只有更大的输入

c - 如何修复在 C 上显示段错误的代码?

javascript - 如何使用 Mac OS 和 Firefox 触发 cmd+h?

c# - 运行 selenium 单元测试时 Firefox 崩溃

python - 将 -profile 参数添加到 python selenium 选项时,Firefox 连接被拒绝

sockets - Wireshark 中的 [TCP ACKed unseen segment] 等是什么?

sockets - 如何在 k8s pod 中使用容器到容器网络配置 TCP active 探测?

c++ - 反转给定大小的链表时出现段错误