Allow subprocess to use posix_spawn()

This is both faster and needed on macOS where one cannot use fork()
when using Qt.
This commit is contained in:
Kovid Goyal 2019-11-25 15:18:13 +05:30
parent 379d1ddfd4
commit b2b4540505
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 8 additions and 16 deletions

View File

@ -6,7 +6,6 @@ __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import subprocess, os, sys, time import subprocess, os, sys, time
from functools import partial
from calibre.constants import iswindows, isosx, isfrozen from calibre.constants import iswindows, isosx, isfrozen
from calibre.utils.config import prefs from calibre.utils.config import prefs
@ -171,7 +170,7 @@ class Worker(object):
'low' : 10, 'low' : 10,
'high' : 20, 'high' : 20,
}[priority] }[priority]
args['preexec_fn'] = partial(renice, niceness) args['env']['CALIBRE_WORKER_NICENESS'] = str(niceness)
ret = None ret = None
if redirect_output: if redirect_output:
self._file = PersistentTemporaryFile('_worker_redirect.log') self._file = PersistentTemporaryFile('_worker_redirect.log')
@ -188,12 +187,6 @@ class Worker(object):
args['stdout'] = windows_null_file args['stdout'] = windows_null_file
args['stderr'] = subprocess.STDOUT args['stderr'] = subprocess.STDOUT
if not iswindows:
# Close inherited file descriptors in worker
# On windows, this is done in the worker process
# itself
args['close_fds'] = True
self.child = subprocess.Popen(cmd, **args) self.child = subprocess.Popen(cmd, **args)
if 'stdin' in args: if 'stdin' in args:
self.child.stdin.close() self.child.stdin.close()

View File

@ -143,7 +143,6 @@ def create_worker(env, priority='normal', cwd=None, func='main'):
def start_pipe_worker(command, env=None, priority='normal', **process_args): def start_pipe_worker(command, env=None, priority='normal', **process_args):
import subprocess import subprocess
from functools import partial
w = Worker(env or {}) w = Worker(env or {})
args = {'stdout':subprocess.PIPE, 'stdin':subprocess.PIPE, 'env':w.env} args = {'stdout':subprocess.PIPE, 'stdin':subprocess.PIPE, 'env':w.env}
args.update(process_args) args.update(process_args)
@ -155,14 +154,8 @@ def start_pipe_worker(command, env=None, priority='normal', **process_args):
'low' : win32process.IDLE_PRIORITY_CLASS}[priority] 'low' : win32process.IDLE_PRIORITY_CLASS}[priority]
args['creationflags'] = win32process.CREATE_NO_WINDOW|priority args['creationflags'] = win32process.CREATE_NO_WINDOW|priority
else: else:
def renice(niceness):
try:
os.nice(niceness)
except:
pass
niceness = {'normal' : 0, 'low' : 10, 'high' : 20}[priority] niceness = {'normal' : 0, 'low' : 10, 'high' : 20}[priority]
args['preexec_fn'] = partial(renice, niceness) args['env']['CALIBRE_WORKER_NICENESS'] = str(niceness)
args['close_fds'] = True
exe = w.executable exe = w.executable
cmd = [exe] if isinstance(exe, string_or_bytes) else exe cmd = [exe] if isinstance(exe, string_or_bytes) else exe

View File

@ -177,6 +177,12 @@ def main():
# so launch the gui as usual # so launch the gui as usual
from calibre.gui2.main import main as gui_main from calibre.gui2.main import main as gui_main
return gui_main(['calibre']) return gui_main(['calibre'])
niceness = os.environ.pop('CALIBRE_WORKER_NICENESS', None)
if niceness:
try:
os.nice(int(niceness))
except Exception:
pass
csw = os.environ.pop('CALIBRE_SIMPLE_WORKER', None) csw = os.environ.pop('CALIBRE_SIMPLE_WORKER', None)
if csw: if csw:
mod, _, func = csw.partition(':') mod, _, func = csw.partition(':')