Использование сокетов (nsIServerSocket) в компоненте XPCOM (расширение Firefox) (сокеты + новое окно = ошибки сегмента) - PullRequest
2 голосов
/ 05 июля 2010

ПОЖАЛУЙСТА, ПРОЧИТАЙТЕ ОБНОВЛЕНИЕ № 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.

Я был бы очень признателен за ответ.Возможно, вы могли бы указать на хороший пример использования Sockets в компоненте XPCOM.Я не видел много таких вокруг.

ОБНОВЛЕНИЕ

Я только что понял, что раньше это работало, так что теперь я думаю, что мой компонент консоли ломает его.Я понятия не имею, как это связано.Но если я не использую этот компонент, сокеты работают нормально.

Вот код моего компонента консоли.Я постараюсь выяснить, что не так и почему это мешает, и позже опубликую свои выводы.Скорее всего, я делаю здесь что-то ужасно неправильное, чтобы вызвать ошибки сегментации с моим javascript =)

Voodoo ..

components / 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); 
} 

I 'используя этот компонент так:

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

Как мой друг и яМожно воспроизвести ошибку, запустив Firefox, после чего должно появиться новое окно с надписью «Открыто гнездо на 9999».Подключитесь с помощью "telnet localhost 9999" и отправьте несколько сообщений.После 2-6 сообщений вы получаете одно из следующих сообщений в терминале, где запущен Firefox:

1 (чаще всего)

Ошибка сегментации

2 (видел несколько раз)

firefox-bin: фатальная ошибка ввода-вывода 11 (ресурс временно недоступен) на X-сервере: 0,0.

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) 'не выполнено.Прервано </p>

Если вам нужна дополнительная информация или вы можете указать мне, где разместить сообщение об ошибке: - / Я буду рад это сделать.

Я знаю, что это только одна измного ошибок ... но, возможно, у вас есть представление о том, что я должен делать по-другому, чтобы избежать этого?Я хотел бы использовать эту мою «консоль» таким образом.

Я попробую сделать это с буфером / сбросом / попыткой / поймать, как предлагают люди, но мне интересно, поймает ли попытка / пойматьСег ошибки ...

1 Ответ

3 голосов
/ 12 июля 2010

Это проблема потока. Обратный вызов 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);
...