daemon: fix daemon when running in binary mode

When running from binary, we need to fixup environment variables
before launching new processes. We also need to detach from the parent
tty, because otherwise it causes problems for PyInstaller.

Plus, when binary is built as --onefile it still creates pop-up terminal
on windows, so we need to switch to --onedir.

Fixes #1446
Fixes #1444

Signed-off-by: Ruslan Kuprieiev <[email protected]>
This commit is contained in:
Ruslan Kuprieiev
2018-12-18 18:13:55 +02:00
parent 4c753ff599
commit e1f736eaad
5 changed files with 47 additions and 17 deletions
+30 -12
View File
@@ -1,27 +1,42 @@
import os
import sys
from subprocess import Popen
from dvc.logger import logger
from dvc.utils import is_binary, fix_env
class Daemon(object): # pragma: no cover
def _spawn_windows(self, cmd):
from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW
CREATE_NEW_PROCESS_GROUP = 0x00000200
DETACHED_PROCESS = 0x00000008
creationflags = CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS
Popen(cmd,
close_fds=True,
shell=False,
creationflags=creationflags)
startupinfo = STARTUPINFO()
startupinfo.dwFlags |= STARTF_USESHOWWINDOW
p = Popen(cmd,
env=fix_env(),
close_fds=True,
shell=False,
creationflags=creationflags,
startupinfo=startupinfo)
p.communicate()
def _spawn_posix(self, cmd):
# NOTE: using os._exit instead of sys.exit, because dvc built
# with PyInstaller has trouble with SystemExit exeption and throws
# errors such as "[26338] Failed to execute script __main__"
try:
pid = os.fork()
if pid > 0:
return
except OSError as exc:
logger.error("Failed at first fork", exc)
sys.exit(1)
os._exit(1)
os.setsid()
os.umask(0)
@@ -29,22 +44,25 @@ class Daemon(object): # pragma: no cover
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
os._exit(0)
except OSError as exc:
logger.error("Failed at second fork", exc)
sys.exit(1)
os._exit(1)
sys.stdin.close()
sys.stdout.close()
sys.stderr.close()
Popen(cmd,
close_fds=True,
shell=False)
p = Popen(cmd,
env=fix_env(),
close_fds=True,
shell=False)
p.communicate()
os._exit(0)
def __call__(self, args):
from dvc.utils import is_binary
cmd = [sys.executable]
if not is_binary():
cmd += ['-m', 'dvc']
+1 -1
View File
@@ -177,7 +177,7 @@ def is_binary():
# NOTE: Fix env variables modified by PyInstaller
# http://pyinstaller.readthedocs.io/en/stable/runtime-information.html
def fix_env(env):
def fix_env(env=None):
if env is None:
env = os.environ.copy()
else:
+14 -2
View File
@@ -13,6 +13,7 @@ fi
BUILD_DIR=build
BIN_DIR=$BUILD_DIR/$INSTALL_DIR/bin
LIB_DIR=$BUILD_DIR/$INSTALL_DIR/lib
print_error()
{
@@ -40,7 +41,7 @@ fpm_build()
{
print_info "Building $1..."
VERSION=$(python -c "import dvc; from dvc import VERSION; print(str(VERSION))")
fpm -s dir -f -t $1 $FPM_FLAGS -n dvc -v $VERSION -C $BUILD_DIR $INSTALL_DIR
fpm -s dir -f -t $1 $FPM_FLAGS -n dvc -v $VERSION -C $BUILD_DIR usr
}
cleanup()
@@ -78,7 +79,18 @@ install_dependencies()
build_dvc()
{
print_info "Building dvc binary..."
pyinstaller --onefile --additional-hooks-dir $(pwd)/scripts/hooks dvc/__main__.py --name dvc --distpath $BIN_DIR --specpath $BUILD_DIR
pyinstaller \
--additional-hooks-dir $(pwd)/scripts/hooks dvc/__main__.py \
--name dvc \
--distpath $LIB_DIR \
--specpath $BUILD_DIR
$LIB_DIR/dvc/dvc --help
mkdir -p $BIN_DIR
pushd $BIN_DIR
ln -s ../lib/dvc/dvc dvc
popd
$BIN_DIR/dvc --help
}
+1 -1
View File
@@ -19,7 +19,7 @@ call pip install -r requirements.txt || goto :error
call pip install pyinstaller || goto :error
echo ====== Building dvc binary... ======
call pyinstaller --onefile --additional-hooks-dir scripts\hooks dvc/__main__.py --name dvc --specpath build
call pyinstaller --additional-hooks-dir scripts\hooks dvc/__main__.py --name dvc --specpath build
echo ====== Copying additional files... ======
copy scripts\innosetup\addSymLinkPermissions.ps1 dist\ || goto :error
+1 -1
View File
@@ -2,7 +2,7 @@
#define MyAppVersion ReadIni(".\scripts\innosetup\config.ini", "Version", "version", "unknown")
#define MyAppPublisher "Dmitry Petrov"
#define MyAppURL "https://dataversioncontrol.com/"
#define MyAppDir "..\..\dist"
#define MyAppDir "..\..\dist\dvc"
[Setup]
AppId={{8258CE8A-110E-4E0D-AE60-FEE00B15F041}