trufflesuite / truffle

:warning: The Truffle Suite is being sunset. For information on ongoing support, migration options and FAQs, visit the Consensys blog. Thank you for all the support over the years.
https://consensys.io/blog/consensys-announces-the-sunset-of-truffle-and-ganache-and-new-hardhat?utm_source=github&utm_medium=referral&utm_campaign=2023_Sep_truffle-sunset-2023_announcement_
MIT License
14.02k stars 2.31k forks source link

hdwallet-provider never being garbage collected #5638

Open Sveagruva opened 2 years ago

Sveagruva commented 2 years ago

Issue

hdwallet-provider not being garbage collected

Steps to Reproduce

create hdwallet-provider track weak reference stop engine


const HDWalletProvider = require("@truffle/hdwallet-provider");

let provider = new HDWalletProvider({
    privateKeys: [privateKey],
    providerOrUrl: process.env.RPC_URL,
});

const  weakRef = new WeakRef(provider);
new Promise(async (resolve, reject) => {
    while(true) {
        await new Promise(resolve => setTimeout(resolve, 1000));
        const providerReferenced = weakRef.deref();

        if(providerReferenced === undefined) {
            console.log("provider garbage collected");
            resolve();
        } else {
            console.log("provider not garbage collected");
        }
    }
});

provider.engine.stop();
provider = null;

Environment

davidmurdoch commented 2 years ago

Interesting. I was able to reproduce this, and even tried enclosing the provider in its own scope just in case the while loop was keep a reference to it some how, but still wasn't seeing the GC happen.

How did you stumble on this issue?

Sveagruva commented 2 years ago

I was creating new provider for every operation on backend with user provided pk. every instance was continuing making web3 requests

davidmurdoch commented 2 years ago

I think I've figured out what is going on. During the lifecycle of a truffle command, like migrate ortest, atruffle-config.jsfile may be loaded several times. Each config instance may have its ownHDWalletProvider, but all set with the same accounts. BecauseHDWalletProvider` tracks the current nonce of each account, if different instances of a provider is used during the life of the command they won't track nonces accurately. To work around this, a nonce tracker singleton object is created and shared among any and all HDWalletProviders. The tracker holds on to a reference to the provider, and since it can never be garbage collected, neither can the providers it references.

You can work around this workaround by setting shareNonce to false (new HDWalletProvider({shareNonce: false})). Which should work fine for you.

The workaround for nonce tracking was the wrong solution and a should be reverted. A proper fix that does not involve a global shared singleton should be implemented.

cliffoo commented 1 year ago

Closing for issue maintenance. Thanks @Sveagruva for bringing this up. If the shareNonce fix suggested by David doesn't work for you feel free to re-open! Thanks.

davidmurdoch commented 1 year ago

@cliffoo this is still an issue I think Truffle should fix the root cause of.