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

Process keep hanging after electron app is closed (Windows) #6357

Closed
rossicler-hostalky opened this issue Jan 5, 2024 · 26 comments
Closed
Labels

Comments

@rossicler-hostalky
Copy link

rossicler-hostalky commented Jan 5, 2024

How frequently does the bug occur?

Always

Description

After closing a realm connection, I expect that realm kills all processes related to Realm, but instead there's always one process that keeps hanging on Windows. This doesn't seem happen on MacOS, just Windows.

Stacktrace & log output

No response

Can you reproduce the bug?

Always

Reproduction Steps

  • First thing you need to setup an electron app, which you can use this template for an easy setup.
  • Go to release/app and run yarn install realm.
  • Create any Realm App with Sync (flexible) enabled.
  • Open the realm connection in the main process of Electron.
  • Close the realm connection before exiting the app.
  • Check task manager for hanging process.

Example code:

...
const app = RealmApp({ id: 'MY_REALM_ID' });

const openRealm = async () => {
    // run realm login

    const realm = await Realm.open({
        schema: [MySchema],
        sync: {
            user: app.currentUser,
            flexible: true,
        }
    });
   realm.close();
}
...

After the above code runs and you close the app, there will be one process from the app still running. If I don't call the function openRealm, all processes are closed.

I also tested without using sync, and for that everything works fine, so I'm guessing it's something related to syncSession. Example:

...
const openLocalRealm = async () => {

    const realm = await Realm.open({
        schema: [MySchema],
    });
   realm.close();
}
...

This code works as expected, no process hangs after app is closed.

Version

11.7.0

What services are you using?

Atlas Device Sync

Are you using encryption?

Yes

Platform OS and version(s)

Windows 10 Pro 22H2

Build environment

Which debugger for React Native: ..

Cocoapods version

No response

@kneth
Copy link
Member

kneth commented Jan 9, 2024

@rossicler-hostalky Thank you for reporting.

I believe that the upgrade to Realm Core v13.9.0 in Realm JS v11.7.0 could be the issue. Please try to upgrade to v11.8.0.

@sync-by-unito sync-by-unito bot added the Waiting-For-Reporter Waiting for more information from the reporter before we can proceed label Jan 9, 2024
@rossicler-hostalky
Copy link
Author

@rossicler-hostalky Thank you for reporting.

I believe that the upgrade to Realm Core v13.9.0 in Realm JS v11.7.0 could be the issue. Please try to upgrade to v11.8.0.

@kneth Thanks for replying.

I tried updating realm to v11.8.0 and also v11.10.2 and no success.

Any idea of what else can I do to get this sorted?

@github-actions github-actions bot added Needs-Attention Reporter has responded. Review comment. and removed Waiting-For-Reporter Waiting for more information from the reporter before we can proceed labels Jan 9, 2024
@kneth
Copy link
Member

kneth commented Jan 10, 2024

@rossicler-hostalky

My guess is that it is the process running the sync client, which cannot terminate. Maybe wtfnode can help us.

It could also be interesting to know if pause() is enough to make the process exit.

@sync-by-unito sync-by-unito bot added Waiting-For-Reporter Waiting for more information from the reporter before we can proceed and removed Needs-Attention Reporter has responded. Review comment. labels Jan 10, 2024
@rossicler-hostalky
Copy link
Author

@kneth

I did try pause() before, and it wasn't enough, but I only tried on v11.7.0.

I will take a look at wtfnode package and try to find more information about the process hanging, once I have more insights I will share here.

@github-actions github-actions bot added Needs-Attention Reporter has responded. Review comment. and removed Waiting-For-Reporter Waiting for more information from the reporter before we can proceed labels Jan 10, 2024
@rossicler-hostalky
Copy link
Author

rossicler-hostalky commented Jan 10, 2024

@kneth

I ran my electron app with wtfnode with and without calling Realm.open, and this is the result of both:

With:

[WTF Node?] open handles:
- Sockets:
  - fd -1
    - Listeners:
Unable to determine callsite for "Function". Did you require `wtfnode` at the top of your entry point?
      - connect: (anonymous) @ unknown:0
Unable to determine callsite for "Function". Did you require `wtfnode` at the top of your entry point?
      - connect: (anonymous) @ unknown:0
Unable to determine callsite for "connect". Did you require `wtfnode` at the top of your entry point?
      - connect: connect @ unknown:0
- Timers:
  - (60000 ~ 60 s) (anonymous) @ C:\Users\...\release\app\node_modules\@realm\network-transport\dist\bundle.cjs.js:78
- Others:
  - Pipe

Without:

[WTF Node?] open handles:
- Others:
  - Pipe

Now, going to ../@realm/network-transport/dist/bundle.cjs.js:78, it looks like it's the function createTimeoutSignal:

createTimeoutSignal(timeoutMs) {
        if (typeof timeoutMs === "number") {
            const controller = new DefaultNetworkTransport.AbortController();
            // Call abort after a specific number of milliseconds
            const timeout = setTimeout(() => {
                controller.abort();
            }, timeoutMs);
            return {
                signal: controller.signal,
                cancelTimeout: () => {
                    clearTimeout(timeout);
                },
            };
        }
        else {
            return {
                signal: undefined,
                cancelTimeout: () => {
                    /* No-op */
                },
            };
        }
    }

@rossicler-hostalky
Copy link
Author

@kneth sorry to ping you again, but any updates regarding this issue?

@kneth
Copy link
Member

kneth commented Jan 17, 2024

@rossicler-hostalky Unfortunately not but your observation is interesting. We need to investigate it a bit more. Update: #6393 might be related.

@rossicler-hostalky
Copy link
Author

@kneth I see, if there's anything more I can to help get this sorted faster, please let me know.

@kneth
Copy link
Member

kneth commented Jan 18, 2024

@rossicler-hostalky I'll bring the issue up at next team meeting

@kneth
Copy link
Member

kneth commented Jan 24, 2024

Unfortunately we haven't been able to find a solution yet. Our current hypothesis is that a Realm Core object is preventing the garbage collector to remove an JavaScript object.

@rossicler-hostalky
Copy link
Author

rossicler-hostalky commented Jan 24, 2024

@kneth Thanks for the update.
I saw that on #6401 completely removed @realm/network-transport from realm. And as wtfnode pointed that package to be where the process hanging is, would it be possible that after that PR is merged this issue would be solved too?
Would it be possible to test that?

@kraenhansen
Copy link
Member

kraenhansen commented Jan 24, 2024

would it be possible that after that PR is merged this issue would be solved too?

Certainly: When that gets merged, we'll be using an AbortSignal, built from AbortSignal.timeout to set the timeout of the request, instead of relying on setTimeout.

The first won't prevent a Node.js process from exiting, while the other would - this can be observed through the difference in:

node -e 'setTimeout(() => console.log("hi"), 1000)'
node -e 'AbortSignal.timeout(1000).addEventListener("abort", () => console.log("hi"))'

If this is indeed the only thing holding your process alive, that should solve it. We do however observe other issues, as @kneth referred to in his comment. I've been experimenting in #6354 but I don't believe I've reached a solution that truly solves the issue for the average user.

@rossicler-hostalky
Copy link
Author

@kraenhansen got it, I'll wait for that to be merged and to test if it's enough for my case.
In the meanwhile, do you know any workaround that I could do to "force" the process to be killed?

The problem I'm having with this is related to electron-updater. When there's a new update to be installed on the user machine, the app will download the new version and try to install, but when it tries to install it says that the app is still running, so it can't install the new version, which leads to the user getting stuck without being able to run the app. This is a major deal breaker, since most users won't that they need to open Task Manager and finish the process from there.

@kraenhansen
Copy link
Member

kraenhansen commented Jan 24, 2024

Realm Studio is calling quitAndInstall here: src/main/Updater.ts#L245.
That might work for you too?

@rossicler-hostalky
Copy link
Author

@kraenhansen I'm already calling quitAndInstall, so that didn't work, but I'm handling the update a little bit differently, instead of asking the user to update, I have a "splash screen" to update automatically when the app is open and before opening the main window, similar to how discord does it.
Not sure if that's the issue, but I'll check Realm Studio and try some things, thanks for the reference.

@kraenhansen
Copy link
Member

Are you passing true, true to quitAndInstall?

@rossicler-hostalky
Copy link
Author

I wasn't before, I did this change according to how it is being done in Realm Studio, but instead of getting an error when trying to install, it seems like it can't reopen the app after this is called.

I followed the process on my task manager, and I see the installer is running on silent mode, but that process closes and the app doesn't open, but that process is still running (realm process).

My guess is that the same way it was giving me an error without running install in silent mode, it can't finish installing because of that process, so it just closes without finishing.

@kneth
Copy link
Member

kneth commented Feb 7, 2024

electron-userland/electron-builder#7294 discuss some of the same issues. The Plugin is a rather radical approach.

@sync-by-unito sync-by-unito bot added Waiting-For-Reporter Waiting for more information from the reporter before we can proceed and removed Needs-Attention Reporter has responded. Review comment. labels Feb 7, 2024
@rossicler-hostalky
Copy link
Author

rossicler-hostalky commented Feb 7, 2024

Thanks for sharing. Although it has some similarities, in my case it's somewhat the opposite, and I could't find a solution in there.
They talk about ways to avoid killing the installer process while installing, and I want the updater to kill any remaining process of the app before installing. I've created this issue electron-userland/electron-builder#8026 in their repository to gather ideas of how to handle this.
No luck yet tho.

EDIT: I found a way to kill the hanging process before installing the update by using patch-package on electron-builder package. If anyone is interest in this, take a look at this comment here

@github-actions github-actions bot added Needs-Attention Reporter has responded. Review comment. and removed Waiting-For-Reporter Waiting for more information from the reporter before we can proceed labels Feb 7, 2024
@kneth
Copy link
Member

kneth commented Feb 8, 2024

@rossicler-hostalky Thank you for sharing the electron issue here, and we will follow it.

@sync-by-unito sync-by-unito bot added Waiting-For-Reporter Waiting for more information from the reporter before we can proceed and removed Needs-Attention Reporter has responded. Review comment. labels Feb 8, 2024
@nirinchev
Copy link
Member

Looks like we have a workaround now and even though there's no clear resolution on the electrong-builder issue, we should be able to close this one.

@nirinchev nirinchev closed this as not planned Won't fix, can't repro, duplicate, stale Mar 20, 2024
@sync-by-unito sync-by-unito bot closed this as completed Mar 20, 2024
@Ahbrown41
Copy link

This is not a usable solution, creates issues when auto upgrading the application as it creates a race condition between old and new instances.

@sync-by-unito sync-by-unito bot reopened this Mar 21, 2024
@nirinchev
Copy link
Member

I'm not sure what that race condition is - the discussion on this issue points to the author having found a solution that works for them. They haven't mentioned race conditions, so if you're experiencing them, you're probably doing something different and you should file a new issue that describes your problem. If you have a repro case, please be sure to include that as that'll help us with the investigation.

@Ahbrown41
Copy link

This thread is recommending that we implement a script that does a task kill in the installer for electron. That is not really a solution. The issue that I have is that as the old version of the application transitions to the new version, this solution as referenced sometimes works, and other times it does not work. When it does not work, the task kill command indiscriminately kills both the new and the old version, causing the application upgrade to fail the upgrade.

What I think everyone is asking for, is a way for us to be able to cleanly shut down realm while synced using the API of the driver that you are providing. Currently we are using the close method and that method is creating this issue.

While I could create a new ticket, there is a flaw with how the driver and realm works that needs to be solved. I would be essentially using the exact same scenario described above.

@nirinchev
Copy link
Member

What you're suggesting is tracked in #4535.

@kneth
Copy link
Member

kneth commented Apr 19, 2024

With v12.7.0 we have introduced the method Realm.shutdown() to gracefully terminate Realm

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 19, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

5 participants