mirror of
https://github.com/YunoHost/moulinette.git
synced 2024-09-03 20:06:31 +02:00
Handle the actual logging from the parent process, otherwise we run into a shitload of complex issues to interact with the websocket
This commit is contained in:
parent
cb5b8c74ec
commit
e85b9f71d5
2 changed files with 27 additions and 29 deletions
|
@ -1,14 +1,13 @@
|
||||||
import time
|
import time
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
|
import threading
|
||||||
|
import queue
|
||||||
|
|
||||||
# This import is unused in this file. It will be deleted in future (W0611 PEP8),
|
# This import is unused in this file. It will be deleted in future (W0611 PEP8),
|
||||||
# but for the momment we keep it due to yunohost moulinette script that used
|
# but for the momment we keep it due to yunohost moulinette script that used
|
||||||
# process.quote syntax to access this module !
|
# process.quote syntax to access this module !
|
||||||
try:
|
from shlex import quote
|
||||||
from pipes import quote # Python2 & Python3 <= 3.2
|
|
||||||
except ImportError:
|
|
||||||
from shlex import quote # Python3 >= 3.3
|
|
||||||
|
|
||||||
from .stream import LogPipe
|
from .stream import LogPipe
|
||||||
|
|
||||||
|
@ -63,9 +62,11 @@ def call_async_output(args, callback, **kwargs):
|
||||||
if a in kwargs:
|
if a in kwargs:
|
||||||
raise ValueError("%s argument not allowed, " "it will be overridden." % a)
|
raise ValueError("%s argument not allowed, " "it will be overridden." % a)
|
||||||
|
|
||||||
kwargs["stdout"] = LogPipe(callback[0])
|
log_queue = queue.Queue()
|
||||||
kwargs["stderr"] = LogPipe(callback[1])
|
|
||||||
stdinfo = LogPipe(callback[2]) if len(callback) >= 3 else None
|
kwargs["stdout"] = LogPipe(callback[0], log_queue)
|
||||||
|
kwargs["stderr"] = LogPipe(callback[1], log_queue)
|
||||||
|
stdinfo = LogPipe(callback[2], log_queue) if len(callback) >= 3 else None
|
||||||
if stdinfo:
|
if stdinfo:
|
||||||
kwargs["pass_fds"] = [stdinfo.fdWrite]
|
kwargs["pass_fds"] = [stdinfo.fdWrite]
|
||||||
if "env" not in kwargs:
|
if "env" not in kwargs:
|
||||||
|
@ -73,27 +74,22 @@ def call_async_output(args, callback, **kwargs):
|
||||||
kwargs["env"]["YNH_STDINFO"] = str(stdinfo.fdWrite)
|
kwargs["env"]["YNH_STDINFO"] = str(stdinfo.fdWrite)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with subprocess.Popen(args, **kwargs) as p:
|
p = subprocess.Popen(args, **kwargs)
|
||||||
kwargs["stdout"].close()
|
|
||||||
kwargs["stderr"].close()
|
while p.poll() is None:
|
||||||
if stdinfo:
|
|
||||||
stdinfo.close()
|
while True:
|
||||||
except TypeError:
|
try:
|
||||||
|
callback, message = log_queue.get_nowait()
|
||||||
|
except queue.Empty:
|
||||||
|
break
|
||||||
|
|
||||||
|
callback(message)
|
||||||
|
finally:
|
||||||
kwargs["stdout"].close()
|
kwargs["stdout"].close()
|
||||||
kwargs["stderr"].close()
|
kwargs["stderr"].close()
|
||||||
if stdinfo:
|
if stdinfo:
|
||||||
stdinfo.close()
|
stdinfo.close()
|
||||||
raise
|
|
||||||
|
|
||||||
# on slow hardware, in very edgy situations it is possible that the process
|
|
||||||
# isn't finished just after having closed stdout and stderr, so we wait a
|
|
||||||
# bit to give hime the time to finish (while having a timeout)
|
|
||||||
# Note : p.poll() returns None is the process hasn't finished yet
|
|
||||||
start = time.time()
|
|
||||||
while time.time() - start < 10:
|
|
||||||
if p.poll() is not None:
|
|
||||||
return p.poll()
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
return p.poll()
|
return p.poll()
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
# Adapted from https://codereview.stackexchange.com/a/17959
|
|
||||||
|
|
||||||
|
|
||||||
class LogPipe(threading.Thread):
|
class LogPipe(threading.Thread):
|
||||||
def __init__(self, log_callback):
|
# Adapted from https://codereview.stackexchange.com/a/17959
|
||||||
|
def __init__(self, log_callback, queue):
|
||||||
"""Setup the object with a logger and a loglevel
|
"""Setup the object with a logger and a loglevel
|
||||||
and start the thread
|
and start the thread
|
||||||
"""
|
"""
|
||||||
|
@ -16,6 +14,8 @@ class LogPipe(threading.Thread):
|
||||||
self.fdRead, self.fdWrite = os.pipe()
|
self.fdRead, self.fdWrite = os.pipe()
|
||||||
self.pipeReader = os.fdopen(self.fdRead)
|
self.pipeReader = os.fdopen(self.fdRead)
|
||||||
|
|
||||||
|
self.queue = queue
|
||||||
|
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
def fileno(self):
|
def fileno(self):
|
||||||
|
@ -25,10 +25,12 @@ class LogPipe(threading.Thread):
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Run the thread, logging everything."""
|
"""Run the thread, logging everything."""
|
||||||
for line in iter(self.pipeReader.readline, ""):
|
for line in iter(self.pipeReader.readline, ""):
|
||||||
self.log_callback(line.strip("\n"))
|
self.queue.put((self.log_callback, line.strip("\n")))
|
||||||
|
|
||||||
self.pipeReader.close()
|
self.pipeReader.close()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""Close the write end of the pipe."""
|
"""Close the write end of the pipe."""
|
||||||
os.close(self.fdWrite)
|
os.close(self.fdWrite)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue