summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2018-06-27 11:31:21 +0200
committerJulian Andres Klode <julian.klode@canonical.com>2018-07-09 16:05:40 +0200
commit21e7f2c41bf00bbe8285dbddf049b63ed3fe0b14 (patch)
tree4bb3598605a176ace7e590e03cfe618d6d1abefd
parentc934279f7a8945d05f383ad67e2c846c4db17791 (diff)
Handle JSON hooks that just close the file/exit and fix some other errors
JSON hooks might disappear and the common idiom to work around hooks disappearing is to check for the hook in the shell snippet that is in the apt.conf file and if it does not exist, do nothing. This caused APT to fail however, expecting it to acknowledge the handshake. Ignoring ECONNRESET on handshakes solves the problem. The error case, and the other error cases also did not stop execution of the hook, causing more errors to pile up. Fix this by directly going to the closing part of the code. LP: #1776218 (cherry picked from commit 1d53cffad22c92645090e0e6ddde31fe4f7c3b05)
-rw-r--r--apt-private/private-json-hooks.cc10
-rwxr-xr-xtest/integration/test-apt-cli-json-hooks87
2 files changed, 95 insertions, 2 deletions
diff --git a/apt-private/private-json-hooks.cc b/apt-private/private-json-hooks.cc
index 07c89ca23..0e4b4913b 100644
--- a/apt-private/private-json-hooks.cc
+++ b/apt-private/private-json-hooks.cc
@@ -387,21 +387,26 @@ bool RunJsonHook(std::string const &option, std::string const &method, const cha
if (size < 0)
{
- _error->Error("Could not read response to hello message from hook %s: %s", Opts->Value.c_str(), strerror(errno));
+ if (errno != ECONNRESET)
+ _error->Error("Could not read response to hello message from hook %s: %s", Opts->Value.c_str(), strerror(errno));
+ goto out;
}
else if (strstr(line, "error") != nullptr)
{
_error->Error("Hook %s reported an error during hello: %s", Opts->Value.c_str(), line);
+ goto out;
}
size = getline(&line, &linesize, F);
if (size < 0)
{
- _error->Error("Could not read message separator line after handshake from %s: %s", Opts->Value.c_str(), strerror(errno));
+ _error->Error("Could not read message separator line after handshake from %s: %s", Opts->Value.c_str(), feof(F) ? "end of file" : strerror(errno));
+ goto out;
}
else if (size == 0 || line[0] != '\n')
{
_error->Error("Expected empty line after handshake from %s, received %s", Opts->Value.c_str(), line);
+ goto out;
}
fwrite(TheData.data(), TheData.size(), 1, F);
@@ -409,6 +414,7 @@ bool RunJsonHook(std::string const &option, std::string const &method, const cha
fwrite(ByeData.data(), ByeData.size(), 1, F);
fwrite("\n\n", 2, 1, F);
+ out:
fclose(F);
// Clean up the sub process
if (ExecWait(Process, Opts->Value.c_str()) == false)
diff --git a/test/integration/test-apt-cli-json-hooks b/test/integration/test-apt-cli-json-hooks
index 0d2a55fb3..80922e01b 100755
--- a/test/integration/test-apt-cli-json-hooks
+++ b/test/integration/test-apt-cli-json-hooks
@@ -120,3 +120,90 @@ HOOK: empty
HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.post","params":{"command":"install","search-terms":["foo"],"unknown-packages":[],"packages":[{"id":1,"name":"foo","architecture":"i386","mode":"install","automatic":false,"versions":{"candidate":{"id":1,"version":"1.0","architecture":"all","pin":500},"install":{"id":1,"version":"1.0","architecture":"all","pin":500}}}]}}
HOOK: empty
HOOK: BYE' apt install foo -s
+
+################## Error in hello response #########################
+
+cat > json-hook.sh << EOF
+#!/bin/bash
+exec 2>/dev/null
+trap '' SIGPIPE
+while true; do
+ read request <&\$APT_HOOK_SOCKET
+ read empty <&\$APT_HOOK_SOCKET
+
+ if echo "\$request" | grep -q ".hello"; then
+ printf '{"jsonrpc": "2.0", "error": {"version": "0.1"}, "id": 0}\n\n' >&\$APT_HOOK_SOCKET
+ break
+ fi
+done
+exit 0
+EOF
+
+
+testfailureequal 'Reading package lists...
+Building dependency tree...
+E: Hook '$HOOK' reported an error during hello: {"jsonrpc": "2.0", "error": {"version": "0.1"}, "id": 0}
+E: Hook '$HOOK' reported an error during hello: {"jsonrpc": "2.0", "error": {"version": "0.1"}, "id": 0}' apt install foo -s
+
+################## Missing separator line #########################
+cat > json-hook.sh << EOF
+#!/bin/bash
+exec 2>/dev/null
+trap '' SIGPIPE
+while true; do
+ read request <&\$APT_HOOK_SOCKET
+ read empty <&\$APT_HOOK_SOCKET
+
+ if echo "\$request" | grep -q ".hello"; then
+ printf '{"jsonrpc": "2.0", "result": {"version": "0.1"}, "id": 0}\n' >&\$APT_HOOK_SOCKET
+ break
+ fi
+done
+exit 0
+EOF
+
+
+testfailureequal 'Reading package lists...
+Building dependency tree...
+E: Could not read message separator line after handshake from '$HOOK': end of file
+E: Could not read message separator line after handshake from '$HOOK': end of file' apt install foo -s
+
+################## Wrong separator line #########################
+cat > json-hook.sh << EOF
+#!/bin/bash
+exec 2>/dev/null
+trap '' SIGPIPE
+while true; do
+ read request <&\$APT_HOOK_SOCKET
+ read empty <&\$APT_HOOK_SOCKET
+
+ if echo "\$request" | grep -q ".hello"; then
+ printf '{"jsonrpc": "2.0", "result": {"version": "0.1"}, "id": 0}\nXX' >&\$APT_HOOK_SOCKET
+ break
+ fi
+done
+exit 0
+EOF
+
+
+testfailureequal 'Reading package lists...
+Building dependency tree...
+E: Expected empty line after handshake from '$HOOK', received XX
+E: Expected empty line after handshake from '$HOOK', received XX' apt install foo -s
+
+##################### Removed hook || true ############################
+cat > rootdir/etc/apt/apt.conf.d/99-json-hooks << EOF
+ AptCli::Hooks::Install:: "true";
+ AptCli::Hooks::Search:: "true";
+EOF
+
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+ foo
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst foo (1.0 unstable [all])
+Conf foo (1.0 unstable [all])' apt install foo -s
+
+
+