[Housekeeping] Close system port when jobs are cancelled (#182)
* Created a test setup that works * Refactored test setup into real-world fixes
This commit is contained in:
parent
2c717e8e7e
commit
17f4bd70f7
6 changed files with 52 additions and 3 deletions
|
|
@ -8,7 +8,7 @@ FROM ${DEV_IMAGE}
|
||||||
# Install debian packages
|
# Install debian packages
|
||||||
RUN apt-get update -qq
|
RUN apt-get update -qq
|
||||||
RUN apt-get install -y inotify-tools ffmpeg curl git openssh-client \
|
RUN apt-get install -y inotify-tools ffmpeg curl git openssh-client \
|
||||||
python3 python3-pip python3-setuptools python3-wheel python3-dev locales
|
python3 python3-pip python3-setuptools python3-wheel python3-dev locales procps
|
||||||
|
|
||||||
# Install nodejs
|
# Install nodejs
|
||||||
RUN curl -sL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh
|
RUN curl -sL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ defmodule Pinchflat.Notifications.CommandRunner do
|
||||||
"""
|
"""
|
||||||
@impl AppriseCommandRunner
|
@impl AppriseCommandRunner
|
||||||
def version do
|
def version do
|
||||||
case System.cmd(backend_executable(), ["--version"]) do
|
case CliUtils.wrap_cmd(backend_executable(), ["--version"]) do
|
||||||
{output, 0} ->
|
{output, 0} ->
|
||||||
output
|
output
|
||||||
|> String.split(~r{\r?\n})
|
|> String.split(~r{\r?\n})
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,23 @@ defmodule Pinchflat.Utils.CliUtils do
|
||||||
|
|
||||||
alias Pinchflat.Utils.StringUtils
|
alias Pinchflat.Utils.StringUtils
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Wraps a command in a shell script that will terminate
|
||||||
|
the command if stdin is closed. Useful for stopping
|
||||||
|
commands if the job runner is cancelled.
|
||||||
|
|
||||||
|
Delegates to `System.cmd/3` and any options/output
|
||||||
|
are passed through.
|
||||||
|
|
||||||
|
Returns {binary(), integer()}
|
||||||
|
"""
|
||||||
|
def wrap_cmd(command, args, opts \\ []) do
|
||||||
|
wrapper_command = Path.join(:code.priv_dir(:pinchflat), "cmd_wrapper.sh")
|
||||||
|
actual_command = [command] ++ args
|
||||||
|
|
||||||
|
System.cmd(wrapper_command, actual_command, opts)
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Parses a list of command options into a list of strings suitable for passing to
|
Parses a list of command options into a list of strings suitable for passing to
|
||||||
`System.cmd/3`.
|
`System.cmd/3`.
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ defmodule Pinchflat.YtDlp.CommandRunner do
|
||||||
formatted_command_opts = [url] ++ CliUtils.parse_options(all_opts)
|
formatted_command_opts = [url] ++ CliUtils.parse_options(all_opts)
|
||||||
Logger.info("[yt-dlp] called with: #{Enum.join(formatted_command_opts, " ")}")
|
Logger.info("[yt-dlp] called with: #{Enum.join(formatted_command_opts, " ")}")
|
||||||
|
|
||||||
case System.cmd(command, formatted_command_opts, stderr_to_stdout: true) do
|
case CliUtils.wrap_cmd(command, formatted_command_opts, stderr_to_stdout: true) do
|
||||||
{_, 0} ->
|
{_, 0} ->
|
||||||
# IDEA: consider deleting the file after reading it. It's in the tmp dir, so it's not
|
# IDEA: consider deleting the file after reading it. It's in the tmp dir, so it's not
|
||||||
# a huge deal, but it's still a good idea to clean up after ourselves.
|
# a huge deal, but it's still a good idea to clean up after ourselves.
|
||||||
|
|
|
||||||
26
priv/cmd_wrapper.sh
Executable file
26
priv/cmd_wrapper.sh
Executable file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# This script is a wrapper for other programs
|
||||||
|
# that ensures they are killed when stdin closes
|
||||||
|
# (eg: a job terminates)
|
||||||
|
|
||||||
|
# Start the program in the background
|
||||||
|
exec "$@" &
|
||||||
|
pid1=$!
|
||||||
|
|
||||||
|
# Silence warnings from here on
|
||||||
|
exec >/dev/null 2>&1
|
||||||
|
|
||||||
|
# Read from stdin in the background and
|
||||||
|
# kill running program when stdin closes
|
||||||
|
exec 0<&0 $(
|
||||||
|
while read; do :; done
|
||||||
|
kill -KILL $pid1
|
||||||
|
) &
|
||||||
|
pid2=$!
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
wait $pid1
|
||||||
|
ret=$?
|
||||||
|
kill -KILL $pid2
|
||||||
|
exit $ret
|
||||||
|
|
@ -3,6 +3,12 @@ defmodule Pinchflat.Utils.CliUtilsTest do
|
||||||
|
|
||||||
alias Pinchflat.Utils.CliUtils
|
alias Pinchflat.Utils.CliUtils
|
||||||
|
|
||||||
|
describe "wrap_cmd/3" do
|
||||||
|
test "delegates to System.cmd/3" do
|
||||||
|
assert {"output\n", 0} = CliUtils.wrap_cmd("echo", ["output"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "parse_options/1" do
|
describe "parse_options/1" do
|
||||||
test "it converts symbol k-v arg keys to kebab case" do
|
test "it converts symbol k-v arg keys to kebab case" do
|
||||||
assert ["--buffer-size", "1024"] = CliUtils.parse_options(buffer_size: 1024)
|
assert ["--buffer-size", "1024"] = CliUtils.parse_options(buffer_size: 1024)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue