Browse Source

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
tags/debian/1.7.0_alpha2
Julian Andres Klode 3 years ago
parent
commit
1d53cffad2
2 changed files with 95 additions and 2 deletions
  1. +8
    -2
      apt-private/private-json-hooks.cc
  2. +87
    -0
      test/integration/test-apt-cli-json-hooks

+ 8
- 2
apt-private/private-json-hooks.cc View File

@@ -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)


+ 87
- 0
test/integration/test-apt-cli-json-hooks View File

@@ -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




Loading…
Cancel
Save