gjs

soup server example of gjs at github - server stops listening after 2 seconds


I was playing around with a soup server example of https://github.com/GNOME/gjs/blob/master/examples/http-server.js
using cjs, but wasnt able to connect to the server with the browser.
Then i checked the open connections with ss -tunl directly after starting the server and saw that, the server opens on localhost port 1080, but after doing a loop of checks with ss, i saw that it disappears, after two seconds, altough cjs is still executing the Main loop.

It took me 2 hours to get it work, but i cant explain, why it now works.

i changed the orginal main function of the example:

function main() {
    let server = new Soup.Server();
    server.add_handler('/', handler);
    server.add_handler('/hello', helloHandler);
    server.listen_local(1080, Soup.ServerListenOptions.IPV4_ONLY);
}

by setting the local server variable to a global variable

var server;
function main() {
    server = new Soup.Server();
    server.add_handler('/', handler);
    server.add_handler('/hello', helloHandler);
    server.listen_local(1080, Soup.ServerListenOptions.IPV4_ONLY);
}

that keeps the server open, but if i change it back to the orginal function, it will again close after two seconds.

Does anybody have some idea? Is this a problem of GLIB MainLoop?


Solution

  • There was a bug open about this that puzzled me, but now that I see your workaround I understand why it is happening. Thank you!

    After main() finishes, the server variable is no longer reachable by any JS code, so it is deleted in the next garbage collection, which apparently happens after about 2 seconds.

    Lifting server out of main() means it is in scope and therefore reachable during the entire execution of the program, so it is not deleted until the end of the program.

    Alternative ways to fix the problem would be to add it as a property on another object that remains in scope (e.g., loop.server = new Soup.Server() or use a Gio.Application subclass and set this.server = new Soup.Server() in its activate method.

    The example code should be fixed to do one of these things.