Fix regression in 2.10 that caused printing to stdout/stderr in FileType plugins to not work when running using calibre-debug -g in a windows console

This commit is contained in:
Kovid Goyal 2014-11-20 17:02:46 +05:30
parent 38fe10d9f9
commit c356e09dcf

View File

@ -12,7 +12,7 @@ from collections import namedtuple
from Queue import Queue
from calibre import detect_ncpus, as_unicode, prints
from calibre.constants import iswindows
from calibre.constants import iswindows, DEBUG
from calibre.ptempfile import PersistentTemporaryFile
from calibre.utils import join_with_timeout
from calibre.utils.ipc import eintr_retry_call
@ -26,9 +26,28 @@ File = namedtuple('File', 'name')
MAX_SIZE = 30 * 1024 * 1024 # max size of data to send over the connection (old versions of windows cannot handle arbitrary data lengths)
worker_kwargs = {'stdout':None}
if iswindows and getattr(sys, 'gui_app', False):
from calibre.utils.ipc.launch import windows_null_file
worker_kwargs['stdout'] = worker_kwargs['stderr'] = windows_null_file
get_stdout_from_child = False
if iswindows:
# The windows console cannot show output from child processes
# created with CREATE_NO_WINDOW, so the stdout/stderr file handles
# the child process inherits will be broken. Similarly, windows GUI apps
# have no usable stdout/stderr file handles. In both these cases, redirect
# the child's stdout/stderr to NUL. If we are running in calibre-debug -g,
# then redirect to PIPE and read from PIPE and print to our stdout.
# Note that when running via the "Restart in debug mode" action, stdout is
# not a console (its already redirected to a log file), so no redirection
# is required.
if getattr(sys, 'gui_app', False) or getattr(sys.stdout, 'isatty', lambda : False)():
if DEBUG:
# We are running in a windows console with calibre-debug -g
import subprocess
get_stdout_from_child = True
worker_kwargs['stdout'] = subprocess.PIPE
worker_kwargs['stderr'] = subprocess.STDOUT
else:
from calibre.utils.ipc.launch import windows_null_file
worker_kwargs['stdout'] = worker_kwargs['stderr'] = windows_null_file
class Failure(Exception):
@ -44,6 +63,10 @@ class Worker(object):
self.process, self.conn = p, conn
self.events = events
self.name = name or ''
if get_stdout_from_child:
t = Thread(target=self.get_stdout, name='PoolWorkerGetOutput-'+self.name)
t.daemon = True
t.start()
def __call__(self, job):
eintr_retry_call(self.conn.send_bytes, cPickle.dumps(job, -1))
@ -66,6 +89,22 @@ class Worker(object):
def set_common_data(self, data):
eintr_retry_call(self.conn.send_bytes, data)
def get_stdout(self):
import time
while self.process.poll() is None:
try:
raw = self.process.stdout.read(1)
if raw:
try:
sys.stdout.write(raw)
except EnvironmentError:
pass
else:
time.sleep(0.1)
except (EOFError, EnvironmentError):
break
class Pool(Thread):
daemon = True
@ -339,6 +378,9 @@ def run_main(func):
with closing(Client(address, authkey=key)) as conn:
raise SystemExit(func(conn))
def test_write():
print ('Printing to stdout in worker')
def test():
def get_results(pool, ignore_fail=False):
ans = {}