Don't enqueue stdout from Meek subprocess in a Thread, just read it as it comes. Solves infinite loop queue read issue on cleanup()

This commit is contained in:
Miguel Jacq 2021-12-15 18:28:55 +11:00
parent 4b18cb7d0f
commit 2689f35635
No known key found for this signature in database
GPG Key ID: EEA4341C6D97A0B6

View File

@ -20,8 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import os import os
import subprocess import subprocess
import time import time
from queue import Queue, Empty
from threading import Thread
class Meek(object): class Meek(object):
@ -67,14 +65,6 @@ class Meek(object):
Start the Meek Client and populate the SOCKS proxies dict Start the Meek Client and populate the SOCKS proxies dict
for use with requests to the Tor Moat API. for use with requests to the Tor Moat API.
""" """
# Small method to read stdout from the subprocess.
# We use this to obtain the random port that Meek
# started on
def enqueue_output(out, queue):
for line in iter(out.readline, b""):
queue.put(line)
out.close()
# Abort early if we can't find the Meek client # Abort early if we can't find the Meek client
if self.meek_client_file_path is None or not os.path.exists( if self.meek_client_file_path is None or not os.path.exists(
self.meek_client_file_path self.meek_client_file_path
@ -124,34 +114,22 @@ class Meek(object):
universal_newlines=True, universal_newlines=True,
) )
# Queue up the stdout from the subprocess for polling later # Obtain the host and port that meek is running on
q = Queue() for line in iter(self.meek_proc.stdout.readline, b""):
t = Thread(target=enqueue_output, args=(self.meek_proc.stdout, q)) if "CMETHOD meek socks5" in line:
t.daemon = True # thread dies with the program self.meek_host = line.split(" ")[3].split(":")[0]
t.start() self.meek_port = line.split(" ")[3].split(":")[1]
self.common.log(
"Meek",
"start",
f"Meek running on {self.meek_host}:{self.meek_port}",
)
break
while True: if "CMETHOD-ERROR" in line:
# read stdout without blocking self.cleanup()
try: raise MeekNotRunning()
line = q.get_nowait() break
self.common.log("Meek", "start", line.strip())
except Empty:
# no stdout yet?
pass
else: # we got stdout
if "CMETHOD meek socks5" in line:
self.meek_host = line.split(" ")[3].split(":")[0]
self.meek_port = line.split(" ")[3].split(":")[1]
self.common.log(
"Meek",
"start",
f"Meek running on {self.meek_host}:{self.meek_port}",
)
break
if "CMETHOD-ERROR" in line:
self.cleanup()
raise MeekNotRunning()
if self.meek_port: if self.meek_port:
self.meek_proxies = { self.meek_proxies = {