brython-dev / brython

Brython (Browser Python) is an implementation of Python 3 running in the browser
BSD 3-Clause "New" or "Revised" License
6.4k stars 511 forks source link

Can't send SharedArrayBuffers between threads #2481

Closed benjie-git closed 3 months ago

benjie-git commented 4 months ago

@PierreQuentel - I see a new problem now, starting with this commit: sending a SharedArrayBuffer from the main thread to a worker is broken. It now arrives as an empty object.

    <script type="text/python" class="webworker" id="testWorker">

from browser import self, bind

@bind(self, "message")
def message(evt):
    self.console.log(evt.data)

    </script>
    <script type="text/python" id="__main__">

from browser import window, worker

def on_ready(myWorker):
    sab = window.SharedArrayBuffer.new(8)
    myWorker.send(sab)

worker.create_worker("testWorker", on_ready, None)

    </script>

logging shows just {} instead of SharedArrayBuffer(8)

I'm afraid testing this is a bit of a pain, as it requires the following headers to be served along with the test page.

{"Cross-Origin-Opener-Policy": "same-origin",
  "Cross-Origin-Embedder-Policy": "require-corp"}
benjie-git commented 3 months ago

This example is fixed, thank you @PierreQuentel ! But I still see what seems like a related issue. This code:

from browser import window
bcastChannel = window.BroadcastChannel.new("TestChannel")
bcastChannel.postMessage("hi there")   # This works.  The following should too, but does not.
bcastChannel.postMessage(["hi", "there"])

Throws the error:

  File "test.html#__main__", line 4, in <module>
    bcastChannel.postMessage(["hi", "there"])
JavascriptError: DataCloneError: Failed to execute 'postMessage' on 'BroadcastChannel': function(self,attr){if(self.__dict__&&$B.$isinstance(self.__dict__,_b_.dict)&&_b_.dict.$contains_string(self.__...<omitted>...)} could not be cloned.

But anything serializable should be valid to send through postMessage().

EricEisaman commented 3 months ago

This example is fixed, thank you @PierreQuentel ! But I still see what seems like a related issue. This code:

from browser import window
bcastChannel = window.BroadcastChannel.new("TestChannel")
bcastChannel.postMessage("hi there")   # This works.  The following should too, but does not.
bcastChannel.postMessage(["hi", "there"])

Throws the error:

  File "test.html#__main__", line 4, in <module>
    bcastChannel.postMessage(["hi", "there"])
JavascriptError: DataCloneError: Failed to execute 'postMessage' on 'BroadcastChannel': function(self,attr){if(self.__dict__&&$B.$isinstance(self.__dict__,_b_.dict)&&_b_.dict.$contains_string(self.__...<omitted>...)} could not be cloned.

But anything serializable should be valid to send through postMessage().

Perhaps related to circular references in the processing of the Array object literal.

benjie-git commented 3 months ago

This is working great for me now. Thank you again for your responsiveness!