aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpukkandan <pukkandan@gmail.com>2021-01-09 17:56:12 +0530
committerpukkandan <pukkandan@gmail.com>2021-01-09 18:08:07 +0530
commitf5b1bca9139fcbac76dca3a6b17e69f53a885988 (patch)
tree2426a3eef3733d998bdcd0ac3d56a42f155ce7d7
parentd9eebbc7471b97f3aa58939685bd7b8f4ce35b1e (diff)
downloadhypervideo-pre-f5b1bca9139fcbac76dca3a6b17e69f53a885988.tar.lz
hypervideo-pre-f5b1bca9139fcbac76dca3a6b17e69f53a885988.tar.xz
hypervideo-pre-f5b1bca9139fcbac76dca3a6b17e69f53a885988.zip
Kill child processes when yt-dlc is killed (https://github.com/ytdl-org/youtube-dl/pull/26592)
Authored by: Unrud
-rw-r--r--youtube_dlc/YoutubeDL.py3
-rw-r--r--youtube_dlc/compat.py3
-rw-r--r--youtube_dlc/downloader/external.py14
-rw-r--r--youtube_dlc/downloader/rtmp.py10
-rw-r--r--youtube_dlc/extractor/openload.py3
-rw-r--r--youtube_dlc/postprocessor/embedthumbnail.py5
-rw-r--r--youtube_dlc/postprocessor/ffmpeg.py5
-rw-r--r--youtube_dlc/utils.py18
8 files changed, 41 insertions, 20 deletions
diff --git a/youtube_dlc/YoutubeDL.py b/youtube_dlc/YoutubeDL.py
index 019b8773e..f648e0904 100644
--- a/youtube_dlc/YoutubeDL.py
+++ b/youtube_dlc/YoutubeDL.py
@@ -99,6 +99,7 @@ from .utils import (
YoutubeDLCookieProcessor,
YoutubeDLHandler,
YoutubeDLRedirectHandler,
+ process_communicate_or_kill,
)
from .cache import Cache
from .extractor import get_info_extractor, gen_extractor_classes, _LAZY_LOADER
@@ -2521,7 +2522,7 @@ class YoutubeDL(object):
['git', 'rev-parse', '--short', 'HEAD'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
cwd=os.path.dirname(os.path.abspath(__file__)))
- out, err = sp.communicate()
+ out, err = process_communicate_or_kill(sp)
out = out.decode().strip()
if re.match('[0-9a-f]+', out):
self._write_string('[debug] Git HEAD: ' + out + '\n')
diff --git a/youtube_dlc/compat.py b/youtube_dlc/compat.py
index 4a69b098f..4a75a336c 100644
--- a/youtube_dlc/compat.py
+++ b/youtube_dlc/compat.py
@@ -2896,6 +2896,7 @@ else:
_terminal_size = collections.namedtuple('terminal_size', ['columns', 'lines'])
def compat_get_terminal_size(fallback=(80, 24)):
+ from .utils import process_communicate_or_kill
columns = compat_getenv('COLUMNS')
if columns:
columns = int(columns)
@@ -2912,7 +2913,7 @@ else:
sp = subprocess.Popen(
['stty', 'size'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, err = sp.communicate()
+ out, err = process_communicate_or_kill(sp)
_lines, _columns = map(int, out.split())
except Exception:
_columns, _lines = _terminal_size(*fallback)
diff --git a/youtube_dlc/downloader/external.py b/youtube_dlc/downloader/external.py
index d2f8f271d..8cd0511fc 100644
--- a/youtube_dlc/downloader/external.py
+++ b/youtube_dlc/downloader/external.py
@@ -22,6 +22,7 @@ from ..utils import (
handle_youtubedl_headers,
check_executable,
is_outdated_version,
+ process_communicate_or_kill,
)
@@ -104,7 +105,7 @@ class ExternalFD(FileDownloader):
p = subprocess.Popen(
cmd, stderr=subprocess.PIPE)
- _, stderr = p.communicate()
+ _, stderr = process_communicate_or_kill(p)
if p.returncode != 0:
self.to_stderr(stderr.decode('utf-8', 'replace'))
return p.returncode
@@ -143,7 +144,7 @@ class CurlFD(ExternalFD):
# curl writes the progress to stderr so don't capture it.
p = subprocess.Popen(cmd)
- p.communicate()
+ process_communicate_or_kill(p)
return p.returncode
@@ -343,14 +344,17 @@ class FFmpegFD(ExternalFD):
proc = subprocess.Popen(args, stdin=subprocess.PIPE, env=env)
try:
retval = proc.wait()
- except KeyboardInterrupt:
+ except BaseException as e:
# subprocces.run would send the SIGKILL signal to ffmpeg and the
# mp4 file couldn't be played, but if we ask ffmpeg to quit it
# produces a file that is playable (this is mostly useful for live
# streams). Note that Windows is not affected and produces playable
# files (see https://github.com/ytdl-org/youtube-dl/issues/8300).
- if sys.platform != 'win32':
- proc.communicate(b'q')
+ if isinstance(e, KeyboardInterrupt) and sys.platform != 'win32':
+ process_communicate_or_kill(proc, b'q')
+ else:
+ proc.kill()
+ proc.wait()
raise
return retval
diff --git a/youtube_dlc/downloader/rtmp.py b/youtube_dlc/downloader/rtmp.py
index fbb7f51b0..8a25dbc8d 100644
--- a/youtube_dlc/downloader/rtmp.py
+++ b/youtube_dlc/downloader/rtmp.py
@@ -89,11 +89,13 @@ class RtmpFD(FileDownloader):
self.to_screen('')
cursor_in_new_line = True
self.to_screen('[rtmpdump] ' + line)
- finally:
+ if not cursor_in_new_line:
+ self.to_screen('')
+ return proc.wait()
+ except BaseException: # Including KeyboardInterrupt
+ proc.kill()
proc.wait()
- if not cursor_in_new_line:
- self.to_screen('')
- return proc.returncode
+ raise
url = info_dict['url']
player_url = info_dict.get('player_url')
diff --git a/youtube_dlc/extractor/openload.py b/youtube_dlc/extractor/openload.py
index 0c20d0177..dfdd0e526 100644
--- a/youtube_dlc/extractor/openload.py
+++ b/youtube_dlc/extractor/openload.py
@@ -17,6 +17,7 @@ from ..utils import (
get_exe_version,
is_outdated_version,
std_headers,
+ process_communicate_or_kill,
)
@@ -226,7 +227,7 @@ class PhantomJSwrapper(object):
self.exe, '--ssl-protocol=any',
self._TMP_FILES['script'].name
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, err = p.communicate()
+ out, err = process_communicate_or_kill(p)
if p.returncode != 0:
raise ExtractorError(
'Executing JS failed\n:' + encodeArgument(err))
diff --git a/youtube_dlc/postprocessor/embedthumbnail.py b/youtube_dlc/postprocessor/embedthumbnail.py
index aaf58e0a0..3055a8c28 100644
--- a/youtube_dlc/postprocessor/embedthumbnail.py
+++ b/youtube_dlc/postprocessor/embedthumbnail.py
@@ -14,7 +14,8 @@ from ..utils import (
PostProcessingError,
prepend_extension,
replace_extension,
- shell_quote
+ shell_quote,
+ process_communicate_or_kill,
)
@@ -128,7 +129,7 @@ class EmbedThumbnailPP(FFmpegPostProcessor):
self._downloader.to_screen('[debug] AtomicParsley command line: %s' % shell_quote(cmd))
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- stdout, stderr = p.communicate()
+ stdout, stderr = process_communicate_or_kill(p)
if p.returncode != 0:
msg = stderr.decode('utf-8', 'replace').strip()
diff --git a/youtube_dlc/postprocessor/ffmpeg.py b/youtube_dlc/postprocessor/ffmpeg.py
index 2141d6311..c6ba1e221 100644
--- a/youtube_dlc/postprocessor/ffmpeg.py
+++ b/youtube_dlc/postprocessor/ffmpeg.py
@@ -21,6 +21,7 @@ from ..utils import (
dfxp2srt,
ISO639Utils,
replace_extension,
+ process_communicate_or_kill,
)
@@ -182,7 +183,7 @@ class FFmpegPostProcessor(PostProcessor):
handle = subprocess.Popen(
cmd, stderr=subprocess.PIPE,
stdout=subprocess.PIPE, stdin=subprocess.PIPE)
- stdout_data, stderr_data = handle.communicate()
+ stdout_data, stderr_data = process_communicate_or_kill(handle)
expected_ret = 0 if self.probe_available else 1
if handle.wait() != expected_ret:
return None
@@ -230,7 +231,7 @@ class FFmpegPostProcessor(PostProcessor):
if self._downloader.params.get('verbose', False):
self._downloader.to_screen('[debug] ffmpeg command line: %s' % shell_quote(cmd))
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
- stdout, stderr = p.communicate()
+ stdout, stderr = process_communicate_or_kill(p)
if p.returncode != 0:
stderr = stderr.decode('utf-8', 'replace')
msg = stderr.strip().split('\n')[-1]
diff --git a/youtube_dlc/utils.py b/youtube_dlc/utils.py
index ae293589b..c99b94423 100644
--- a/youtube_dlc/utils.py
+++ b/youtube_dlc/utils.py
@@ -2215,6 +2215,15 @@ def unescapeHTML(s):
r'&([^&;]+;)', lambda m: _htmlentity_transform(m.group(1)), s)
+def process_communicate_or_kill(p, *args, **kwargs):
+ try:
+ return p.communicate(*args, **kwargs)
+ except BaseException: # Including KeyboardInterrupt
+ p.kill()
+ p.wait()
+ raise
+
+
def get_subprocess_encoding():
if sys.platform == 'win32' and sys.getwindowsversion()[0] >= 5:
# For subprocess calls, encode with locale encoding
@@ -3730,7 +3739,8 @@ def check_executable(exe, args=[]):
""" Checks if the given binary is installed somewhere in PATH, and returns its name.
args can be a list of arguments for a short output (like -version) """
try:
- subprocess.Popen([exe] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+ process_communicate_or_kill(subprocess.Popen(
+ [exe] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE))
except OSError:
return False
return exe
@@ -3744,10 +3754,10 @@ def get_exe_version(exe, args=['--version'],
# STDIN should be redirected too. On UNIX-like systems, ffmpeg triggers
# SIGTTOU if youtube-dlc is run in the background.
# See https://github.com/ytdl-org/youtube-dl/issues/955#issuecomment-209789656
- out, _ = subprocess.Popen(
+ out, _ = process_communicate_or_kill(subprocess.Popen(
[encodeArgument(exe)] + args,
stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
except OSError:
return False
if isinstance(out, bytes): # Python 2.x
@@ -5706,7 +5716,7 @@ def write_xattr(path, key, value):
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
except EnvironmentError as e:
raise XAttrMetadataError(e.errno, e.strerror)
- stdout, stderr = p.communicate()
+ stdout, stderr = process_communicate_or_kill(p)
stderr = stderr.decode('utf-8', 'replace')
if p.returncode != 0:
raise XAttrMetadataError(p.returncode, stderr)