Bug 247372 - MessagePort failing to receive postmessage events
Summary: MessagePort failing to receive postmessage events
Status: RESOLVED DUPLICATE of bug 193184
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: Safari 16
Hardware: All All
: P2 Major
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-11-02 11:08 PDT by Tom
Modified: 2022-11-02 13:03 PDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tom 2022-11-02 11:08:32 PDT
See https://github.com/GoogleChromeLabs/comlink/issues/600.

The basic pattern comlink uses creates a MessageChannel, keeps one MessagePort for itself and transfers the other to the web worker.  It subscribes to the port it keeps for itself using AddEventListener, but otherwise does not retain a reference to that port, apart from the callback to AddEventListener which should keep the port alive...except, under certain conditions (memory pressure being a key factor), the port it keeps stops receiving message events from the paired web worker.  Once it stops receiving messages, it appears to stop forever -- it's not the case it drops occasional messages, but rather it just appears to permanently break.

A work around that has 100% mitigated the problem in our application is to patch the MessagePort add/remove event listener methods to add an explicit reference to the MessagePort.  E.g., this isn't what we did exactly, but it illustrates the idea:


        const retainedPorts = new Set();
        const pAddEventListener = MessagePort.prototype.addEventListener;
        MessagePort.prototype.addEventListener = function (
            type: string,
            listener: EventListenerOrEventListenerObject,
            options?: boolean | AddEventListenerOptions
        ) {
            if (type === 'message') {
                retainedPorts.add(this);
            }

            pAddEventListener.call(this, type, listener, options);
        }


With that change, the MessagePort keeps receiving messages.  Since a main effect of adding that reference within the Set is to keep the MessagePort from being garbage collected, my best guess is that Safari is inappropriately garbage collecting the port under certain conditions.  It is far from a 100% repro, however.

Our app uses postmessage to web workers in core infrastructure, so this issue completely breaks us, which is why I marked this as major. I see a couple other issues reported in this space, but these have been active for years without being addressed and are not reflective, I think, of the severity.

https://bugs.webkit.org/show_bug.cgi?id=193184
https://bugs.webkit.org/show_bug.cgi?id=184502
Comment 1 Tom 2022-11-02 11:41:12 PDT
I should have said the first link appears active for years.  The second one is resolved.  Sorry!
Comment 2 Alexey Proskuryakov 2022-11-02 13:03:38 PDT
This does seem like an exact duplicate of bug 193184 though? I'll ping a few folks offline, but adding a comment there would have achieved the same result.

*** This bug has been marked as a duplicate of bug 193184 ***