aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-02-18 08:33:32 +0800
committerRunxi Yu <me@runxiyu.org>2025-02-18 08:33:32 +0800
commit7b08b7b712c51a99e1b76483c4c202488d987da4 (patch)
treeb6d159aea98f1858d0f4271fa4c9c54cd74eff62
parentrepo_index.html: Move the repo description before the clone URLs (diff)
downloadforge-7b08b7b712c51a99e1b76483c4c202488d987da4.tar.gz
forge-7b08b7b712c51a99e1b76483c4c202488d987da4.tar.zst
forge-7b08b7b712c51a99e1b76483c4c202488d987da4.zip
hooks: Fix the race condition that causes EPIPE
The hooks handler in the main daemon didn't wait for the hook client to write fully, and sometimes prematurely closes the connection, causing the hook client's splice to return EPIPE (or SIGPIPE if the signal handler wasn't installed). To remedy this, we call shutdown(sock, SHUT_WR) in the client, so that attempts to read on the server side return EOF. Then we can simply use io.Copy(&buf, conn) on the server side to fetch all of the data into a buffer.
Diffstat (limited to '')
-rw-r--r--git_hooks_client/git_hooks_client.c10
-rw-r--r--git_hooks_handle.go7
2 files changed, 17 insertions, 0 deletions
diff --git a/git_hooks_client/git_hooks_client.c b/git_hooks_client/git_hooks_client.c
index e00ab3a..6471aa8 100644
--- a/git_hooks_client/git_hooks_client.c
+++ b/git_hooks_client/git_hooks_client.c
@@ -163,6 +163,16 @@ int main(int argc, char *argv[]) {
}
/*
+ * The sending part of the UNIX socket should be shut down, to let
+ * io.Copy on the Go side return.
+ */
+ if (shutdown(sock, SHUT_WR) == -1) {
+ perror("shutdown internal socket");
+ close(sock);
+ return EXIT_FAILURE;
+ }
+
+ /*
* The first byte of the response from the UNIX domain socket is the
* status code. We read it and record it as our return value.
*/
diff --git a/git_hooks_handle.go b/git_hooks_handle.go
index 91f1894..e9b163a 100644
--- a/git_hooks_handle.go
+++ b/git_hooks_handle.go
@@ -5,6 +5,7 @@ import (
"encoding/binary"
"errors"
"fmt"
+ "io"
"net"
"os"
"path/filepath"
@@ -72,6 +73,12 @@ func hooks_handle_connection(conn net.Conn) {
args = append(args, arg.String())
}
+ var stdin bytes.Buffer
+ _, err = io.Copy(&stdin, conn)
+ if err != nil {
+ fmt.Fprintln(conn, "Failed to read to the stdin buffer:", err.Error())
+ }
+
switch filepath.Base(args[0]) {
case "pre-receive":
if pack_to_hook.direct_access {