How to use pyngrok with multi-threading?

i'm trying to run a python script with 3 threads one of them is to port forward coming connections to localhost using pyngrok using the threading module, but the issue is that whenever the ngrok server starts it hangs all other threads...

    def CreateTunnel(self):
        try:
            ngrok.set_auth_token(self.AuthToken)

            print(f"{Fore.GREEN}[+] Opening TCP tunnel 👌{Style.RESET_ALL}")
            tunnel = ngrok.connect(addr=self.port, proto="tcp")

            print(f"{Fore.GREEN}[+] Public URL:{Style.RESET_ALL} {Fore.CYAN}{ngrok.get_tunnels()[0]}{Style.RESET_ALL}")
            ngrok_proc = ngrok.get_ngrok_process()
            self.pub_url = tunnel.public_url.split("tcp://")[1]
            self.ngrokPort = tunnel.public_url.split("tcp://")[1].split(":")[1]

            ngrok_proc.proc.wait()  # Hangs the process and other threads stops execution

How can i run the 3 threads synchronously? or how i can setup an ngrok server without needing to use proc.wait()?

here is how the threads are called:

def Threads(self):
        # Adding them to a list
        if self.ngrok:
            self.jobs.append(th(target=self.CreateTunnel()))

        self.jobs.append(th(target=self.listen()))
        self.jobs.append(th(target=self.brute()))

        # Starting them
        for job in self.jobs:
            th.setDaemon(True)
            th.start()

Solution 1:

check this out

def Threads(self):
    # Adding them to a list
    if self.ngrok:
        self.jobs.append(th(target=self.CreateTunnel()))

    self.jobs.append(th(target=self.listen()))
    #self.jobs.append(th(target=self.brute()))

    # Starting them
    for job in self.jobs:
        th.setDaemon(True)
        th.start()


def CreateTunnel(self):
    try:
        ngrok.set_auth_token(self.AuthToken)

        print(f"{Fore.GREEN}[+] Opening TCP tunnel 👌{Style.RESET_ALL}")
        tunnel = ngrok.connect(addr=self.port, proto="tcp")

        print(f"{Fore.GREEN}[+] Public URL:{Style.RESET_ALL} {Fore.CYAN}{ngrok.get_tunnels()[0]}{Style.RESET_ALL}")
        ngrok_proc = ngrok.get_ngrok_process()
        self.pub_url = tunnel.public_url.split("tcp://")[1]
        self.ngrokPort = tunnel.public_url.split("tcp://")[1].split(":")[1]

        ngrok_proc.proc.wait()  # Hangs the process and other threads stops execution

Good Luck🏃🏼‍♂️🏃🏼‍♂️