Skip to content

Commit ec7dbd1

Browse files
committed
receive-pack: allow hooks to ignore its standard input stream
The pre-receive and post-receive hooks were designed to be an improvement over old style update and post-update hooks, which take the update information on their command line and are limited by the command line length limit. The same information is fed from the standard input to pre/post-receive hooks instead to lift this limitation. It has been mandatory for these new style hooks to consume the update information fully from the standard input stream. Otherwise, they would risk killing the receive-pack process via SIGPIPE. If a hook does not want to look at all the information, it is easy to send its standard input to /dev/null (perhaps a niche use of hook might need to know only the fact that a push was made, without having to know what objects have been pushed to update which refs), and this has already been done by existing hooks that are written carefully. However, because there is no good way to consistently fail hooks that do not consume the input fully (a small push may result in a short update record that may fit within the pipe buffer, to which the receive-pack process may manage to write before the hook has a chance to exit without reading anything, which will not result in a death-by-SIGPIPE of receive-pack), it can lead to a hard to diagnose "once in a blue moon" phantom failure. Lift this "hooks must consume their input fully" mandate. A mandate that is not enforced strictly is not helping us to catch mistakes in hooks. If a hook has a good reason to decide the outcome of its operation without reading the information we feed it, let it do so as it pleases. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 96db324 commit ec7dbd1

File tree

2 files changed

+19
-0
lines changed

2 files changed

+19
-0
lines changed

builtin/receive-pack.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "connected.h"
1616
#include "argv-array.h"
1717
#include "version.h"
18+
#include "sigchain.h"
1819

1920
static const char receive_pack_usage[] = "git receive-pack <git-dir>";
2021

@@ -288,6 +289,8 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_sta
288289
return code;
289290
}
290291

292+
sigchain_push(SIGPIPE, SIG_IGN);
293+
291294
while (1) {
292295
const char *buf;
293296
size_t n;
@@ -299,6 +302,9 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_sta
299302
close(proc.in);
300303
if (use_sideband)
301304
finish_async(&muxer);
305+
306+
sigchain_pop(SIGPIPE);
307+
302308
return finish_command(&proc);
303309
}
304310

t/t5401-update-hooks.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,17 @@ test_expect_success 'send-pack stderr contains hook messages' '
135135
test_cmp expect actual
136136
'
137137

138+
test_expect_success 'pre-receive hook that forgets to read its input' '
139+
write_script victim.git/hooks/pre-receive <<-\EOF &&
140+
exit 0
141+
EOF
142+
rm -f victim.git/hooks/update victim.git/hooks/post-update &&
143+
144+
for v in $(test_seq 100 999)
145+
do
146+
git branch branch_$v master || return
147+
done &&
148+
git push ./victim.git "+refs/heads/*:refs/heads/*"
149+
'
150+
138151
test_done

0 commit comments

Comments
 (0)