Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
wiwichips opened this issue Jan 31, 2024 · 7 comments · Fixed by #236
Closed

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

wiwichips opened this issue Jan 31, 2024 · 7 comments · Fixed by #236
Assignees
Labels
bug Something isn't working

Comments

@wiwichips
Copy link
Collaborator

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

@wiwichips
Copy link
Collaborator Author

wiwichips commented Jan 31, 2024

@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 )

@wiwichips
Copy link
Collaborator Author

@wiwichips wiwichips added the bug Something isn't working label Feb 5, 2024
@philippedistributive
Copy link
Collaborator

philippedistributive commented Feb 8, 2024

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

@philippedistributive
Copy link
Collaborator

@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

@philippedistributive
Copy link
Collaborator

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

@philippedistributive
Copy link
Collaborator

philippedistributive commented Feb 12, 2024

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

@philippedistributive
Copy link
Collaborator

looks fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants