Skip to content

segmentation fault after 60 seconds when trying to load socket.io #232

Closed

Description

@wiwichips

Issue type

Bug

How did you install PythonMonkey?

None

OS platform and distribution

Ubuntu 22.04

Python version (python --version)

Python 3.10.12

PythonMonkey version (pip show pythonmonkey)

main branch

Bug Description

Title

seg fault after 60 seconds on when attempting to load the browser socketio bundle into pythonmonkey!

Repro

Client Side (the place where the seg fault shows up)

client side socketio pmjs pythonmonkey code

pmjs PythonMonkey JavaScript code for the client:
client-socketio-pmjs.js

#!/usr/bin/env pmjs
const io = require('./socket.io.min.js');

const socket = io('http://localhost:3490');

console.log(socket.on);
console.log(socket.emit);

socket.onAny((eventName, ...args) => {
  console.log(eventName);
  console.log(args);
});


socket.on('connect', () => {
    console.log('Connected to the server');
    socket.emit('clientMessage', 'hello from JS client');
});

socket.on('serverMessage', (msg) => {
    console.log('Message from server:', msg);
    socket.disconnect();
});

socket.on('disconnect', () => {
    console.log('Disconnected from the server');
});

socket.io.min.js downloaded from --> https://cdn.socket.io/4.7.4/socket.io.min.js

  • just use the file I send in my slack message, not sure if this is the same one.... probably is, but use the file I sent in my slack message to make sure you're 100% using the same one as me...

how to run the client

pmjs client-socketio-pmjs.js

The NodeJS SocketIO server I happen to have talking to this client

code for the nodejs socketio server

node NodeJS JavaScript code for the server
server-socketio-nodejs.js

#!/usr/bin/env node

const http = require('http');
const server = http.createServer();
const io = require('socket.io')(server, {
    cors: {
        origin: "*"
    }
});

io.on('connection', (socket) => {
    console.log('A client connected');

    socket.on('clientMessage', (msg) => {
        console.log('Message from client:', msg);
        socket.emit('serverMessage', 'OK I GOT IT');
    });

    socket.on('disconnect', () => {
        console.log('A client disconnected');
    });
});

server.listen(3490, () => {
    console.log('Server listening on port 3490');
});

package.json

{
  "dependencies": {
    "socket.io": "^4.7.4",
    "socket.io-client": "^4.7.4",
    "socketio": "^1.0.0"
  }
}

instructions to run nodejs socketio server:

npm i
node server-socketio-nodejs.js

Refer to this slack message on the private Distributive slack which only Distributive developers have access to: https://dstrbtv.slack.com/archives/C03RNFRL4NQ/p1706703736711539

Standalone code to reproduce the issue

Put my code above,

Relevant log output or backtrace

(pythonmonkey-py3.10) will@bestia:~/test/challenge-dcp-client-pm ➡ time ./client_socketio.js 
[Function]
[Function: value]
Segmentation fault (core dumped)

real	1m1.459s
user	0m0.207s
sys	0m0.065s

Additional info if applicable

No response

What branch of PythonMonkey were you developing on? (If applicable)

main

Activity

  1. wiwichips commented on Jan 31, 2024

    @wiwichips
    CollaboratorAuthor

    @Xmader said:
    xhr.open gets called but xhr.send doesn't. Seems that the connection dies somewhere between xhr.open and xhr.send.


    socketio makes a check to see if withcredentials is defined as a property of xhr, and if it isn't it tries anyways! I think its still a seg fault, I don't remember - but keep that in mine ( whoever works on this )

  2. philippedistributive commented on Feb 8, 2024

    @philippedistributive
    Contributor

    Slack channel, Thursday February 1st:

    Tom Tang (@Xmader)
    9:30 AM
    socketio aways says Disconnected from the server: ping timeout .
    After few hours of debugging , the reason is that there's something wrong with our clearTimeout API.
    https://github.com/socketio/socket.io-client/blob/8cfea8c/dist/socket.io.js#L2194-L2197 old timers don't get cancelled properly, so the connection is closed prematurely.

    socket.io.js
    this.clearTimeoutFn(this.pingTimeoutTimer);
    this.pingTimeoutTimer = this.setTimeoutFn(function () {
    _this5.onClose("ping timeout");
    }, this.pingInterval + this.pingTimeout);

    Tom Tang
    9:41 AM
    When socketio calling clearTimeout , the timeoutId argument is a double (JSVAL_TYPE_DOUBLE), so https://github.com/Distributive-Network/PythonMonkey/blob/116f600/src/internalBinding/timers.cc#L48-L53 can't work properly (I assume integer JS number is always optimized to a int32 despite JS number should be a double).
    However when calling clearTimeout directly, the timeoutId argument is of correct type JSVAL_TYPE_INT32 . It's maybe another kind of optimization in SpiderMonkey.
    timers.cc
    if (!timeoutIdArg.isInt32()) {
    return true;
    }

    // Retrieve the AsyncHandle by timeoutID

    min repro:
    (socket.io uses engine.io under the hood)

    code at https://drive.google.com/drive/folders/1YKotvr0KTsXgXDVbMWgy-D2O6HcxSpZO

  3. philippedistributive commented on Feb 9, 2024

    @philippedistributive
    Contributor

    @Xmader trying the code above, I get
    node eio-server.js
    /home/philippe/bug232/eio-server.js:2
    const server = engine.listen(3491, {});
    ^

    TypeError: engine.listen is not a function
    at Object. (/home/philippe/bug232/eio-server.js:2:23)
    at Module._compile (node:internal/modules/cjs/loader:1356:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1414:10)
    at Module.load (node:internal/modules/cjs/loader:1197:32)
    at Module._load (node:internal/modules/cjs/loader:1013:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:128:12)
    at node:internal/main/run_main_module:28:49

    Node.js v18.19.0

    Indeed:
    more engine.io.js | grep listen

    • Adds an event listener that will be invoked a single
      Emitter.prototype.listeners = function (event) {
      return !!this.listeners(event).length;
      • Adds event listeners to the socket
        // Firefox closes the connection when the "beforeunload" event is emitted but not Chrome. This event listener
        // Emit error on next tick so it can be listened to
        // set up transport listeners
        // Remove all listeners on the transport and on self
        // listener already closed the socket

    Please provide a full reproducer sample

  4. philippedistributive commented on Feb 12, 2024

    @philippedistributive
    Contributor

    I could repro the crash with Will's code sometimes and other times not. Stack trace is:

    #0 0x0000000000076e53 in ?? ()
    #1 0x00007efe8e9b26c2 in cfunction_vectorcall_NOARGS (func=0x7efe88dc92b0, args=,
    nargsf=, kwnames=) at Objects/methodobject.c:486
    #2 0x00007efe8ea771eb in _PyObject_VectorcallTstate (kwnames=,
    nargsf=, args=, callable=0x7efe88dc92b0,
    tstate=0x7efe8ed8cf18 <_PyRuntime+166328>) at ./Include/internal/pycore_call.h:92
    #3 context_run (self=0x7efe88dc5ec0, args=, nargs=,
    kwnames=) at Python/context.c:673
    #4 0x00007efe8e9b2456 in cfunction_vectorcall_FASTCALL_KEYWORDS (func=0x7efe8937da80,
    args=0x7efe88d0c928, nargsf=, kwnames=)
    at Objects/methodobject.c:443
    #5 0x00007efe8e905956 in do_call_core (use_tracing=, kwdict=0x0,
    callargs=0x7efe88d0c910, func=0x7efe8937da80, tstate=) at Python/ceval.c:7352
    #6 _PyEval_EvalFrameDefault (tstate=, frame=,
    throwflag=) at Python/ceval.c:5376
    #7 0x00007efe8ea5d7f4 in _PyEval_EvalFrame (throwflag=0, frame=0x7efe8ef37020,
    tstate=0x7efe8ed8cf18 <_PyRuntime+166328>) at ./Include/internal/pycore_ceval.h:73
    #8 _PyEval_Vector (args=0x0, argcount=0, kwnames=0x0, locals=0x7efe8e7f6b00, func=0x7efe8e7d5f80,
    tstate=0x7efe8ed8cf18 <_PyRuntime+166328>) at Python/ceval.c:6434
    #9 PyEval_EvalCode (co=co@entry=0x7efe8e7a4670, globals=globals@entry=0x7efe8e7f6b00,
    locals=locals@entry=0x7efe8e7f6b00) at Python/ceval.c:1148
    #10 0x00007efe8eaa8079 in run_eval_code_obj (locals=0x7efe8e7f6b00, globals=0x7efe8e7f6b00,
    co=0x7efe8e7a4670, tstate=0x7efe8ed8cf18 <_PyRuntime+166328>) at Python/pythonrun.c:1710
    #11 run_mod (mod=mod@entry=0x55a3b0cd3c28, filename=filename@entry=0x7efe8ed69a70 <_PyRuntime+21776>,
    --Type for more, q to quit, c to continue without paging--
    globals=globals@entry=0x7efe8e7f6b00, locals=locals@entry=0x7efe8e7f6b00, flags=flags@entry=0x7fff4f9e3b08,
    arena=arena@entry=0x7efe8e71b7d0) at Python/pythonrun.c:1731
    #12 0x00007efe8eaaa20f in PyRun_StringFlags (
    str=str@entry=0x7efe8e773240 "import sys; from importlib import import_module; sys.argv = ['/home/philippe/.cache/pypoetry/virtualenvs/pythonmonkey-n83Wr7Le-py3.11/bin/pmjs', 'client-socketio-pmjs.js']; sys.exit(import_module('pyt"...,
    start=start@entry=257, globals=0x7efe8e7f6b00, locals=0x7efe8e7f6b00, flags=flags@entry=0x7fff4f9e3b08)
    at Python/pythonrun.c:1601
    #13 0x00007efe8eaaa27f in PyRun_SimpleStringFlags (
    command=0x7efe8e773240 "import sys; from importlib import import_module; sys.argv = ['/home/philippe/.cache/pypoetry/virtualenvs/pythonmonkey-n83Wr7Le-py3.11/bin/pmjs', 'client-socketio-pmjs.js']; sys.exit(import_module('pyt"...,
    flags=flags@entry=0x7fff4f9e3b08) at Python/pythonrun.c:487
    #14 0x00007efe8eaca7a3 in pymain_run_command (command=) at Modules/main.c:255
    #15 pymain_run_python (exitcode=0x7fff4f9e3b00) at Modules/main.c:592
    #16 Py_RunMain () at Modules/main.c:680
    #17 0x00007efe8eacb3fe in pymain_main (args=0x7fff4f9e3c20) at Modules/main.c:710
    #18 Py_BytesMain (argc=, argv=) at Modules/main.c:734
    #19 0x00007efe8e428150 in __libc_start_call_main (main=main@entry=0x55a3af0b3060

    , argc=argc@entry=3,
    argv=argv@entry=0x7fff4f9e3da8) at ../sysdeps/nptl/libc_start_call_main.h:58
    #20 0x00007efe8e428209 in __libc_start_main_impl (main=0x55a3af0b3060 , argc=3, argv=0x7fff4f9e3da8,
    init=, fini=, rtld_fini=, stack_end=0x7fff4f9e3d98)
    at ../csu/libc-start.c:360
    #21 0x000055a3af0b3095 in _start ()

    -> so nothing obviously ours and the top item is missing

  5. philippedistributive commented on Feb 12, 2024

    @philippedistributive
    Contributor

    Now got:

    Exception in callback JSFunctionProxy.eventLoopJobWrapper()
    handle: <TimerHandle when=93467.359174243 JSFunctionProxy.eventLoopJobWrapper()>
    Traceback (most recent call last):
    File "/home/philippe/.pyenv/versions/3.11.7/lib/python3.11/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
    pythonmonkey.SpiderMonkeyError: uncaught exception: out of memory

    Do we have a memory leak?

    The above exception was the direct cause of the following exception:

    Traceback (most recent call last):
    File "/home/philippe/.pyenv/versions/3.11.7/lib/python3.11/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
    File "/home/philippe/.pyenv/versions/3.11.7/lib/python3.11/asyncio/locks.py", line 191, in set
    if not fut.done():
    ^^^^^^^^^^
    SystemError: <method 'done' of '_asyncio.Future' objects> returned a result with an exception set

  6. philippedistributive commented on Feb 16, 2024

    @philippedistributive
    Contributor

    looks fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions