From ca92f1c0aa9cd2461d8834ab26441c60b3ac3def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Mon, 10 Aug 2020 18:01:53 +0200 Subject: [PATCH] Pipe the deliveries and payload into stage 3 instead of passing them in argv Also removes a useless chdir to the cwd in the fork Closes: ~sircmpwn/git.sr.ht#279 --- gitsrht-update-hook/post-update.go | 23 +++++++++++++++++------ gitsrht-update-hook/stage-3.go | 21 +++++++++++++++++++-- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/gitsrht-update-hook/post-update.go b/gitsrht-update-hook/post-update.go index 1021efc..8b9c4e9 100644 --- a/gitsrht-update-hook/post-update.go +++ b/gitsrht-update-hook/post-update.go @@ -6,6 +6,7 @@ import ( "fmt" "log" "os" + "strconv" "strings" "syscall" @@ -335,28 +336,38 @@ func postUpdate() { return } - // Run stage 3 asyncronously - the last few tasks can be done without + // Run stage 3 asynchronously - the last few tasks can be done without // blocking the pusher's terminal. - wd, err := os.Getwd() - if err != nil { + var stage3Pipe [2]int + if err := syscall.Pipe(stage3Pipe[:]); err != nil { log.Fatalf("Failed to execute stage 3: %v", err) } + syscall.CloseOnExec(stage3Pipe[1]) procAttr := syscall.ProcAttr{ - Dir: wd, - Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}, + Dir: "", + Files: []uintptr{uintptr(stage3Pipe[0]), os.Stdout.Fd(), os.Stderr.Fd()}, Env: os.Environ(), Sys: &syscall.SysProcAttr{ Foreground: false, }, } pid, err := syscall.ForkExec(hook, []string{ - "hooks/stage-3", string(deliveriesJson), string(payloadBytes), + "hooks/stage-3", + strconv.Itoa(len(deliveriesJson)), strconv.Itoa(len(payloadBytes)), }, &procAttr) if err != nil { log.Fatalf("Failed to execute stage 3: %v", err) } + stage3File := os.NewFile(uintptr(stage3Pipe[1]), "stage3 IPC") + if _, err = stage3File.Write(deliveriesJson); err != nil { + log.Fatalf("Failed to execute stage 3: %v", err) + } + if _, err = stage3File.Write(payloadBytes); err != nil { + log.Fatalf("Failed to execute stage 3: %v", err) + } + logger.Printf("Executing stage 3 to record %d sync deliveries and make "+ "%d async deliveries (pid %d)", len(deliveries), len(dbinfo.AsyncWebhooks), pid) diff --git a/gitsrht-update-hook/stage-3.go b/gitsrht-update-hook/stage-3.go index b445e37..2c01fbe 100644 --- a/gitsrht-update-hook/stage-3.go +++ b/gitsrht-update-hook/stage-3.go @@ -4,6 +4,7 @@ import ( "database/sql" "encoding/json" "os" + "strconv" _ "github.com/lib/pq" ) @@ -30,10 +31,26 @@ func stage3() { var subscriptions []WebhookSubscription var deliveries []WebhookDelivery - if err := json.Unmarshal([]byte(os.Args[1]), &deliveries); err != nil { + deliveriesJsonLen, err := strconv.Atoi(os.Args[1]) + if err != nil { + logger.Fatalf("deliveriesJson length \"%v\": %v", string(os.Args[1]), err) + } + deliveriesJson := make([]byte, deliveriesJsonLen) + if read, err := os.Stdin.Read(deliveriesJson); read != len(deliveriesJson) { + logger.Fatalf("Failed to read deliveries: %v, %v", read, err) + } + if err := json.Unmarshal(deliveriesJson, &deliveries); err != nil { logger.Fatalf("Unable to unmarhsal delivery array: %v", err) } - payload := []byte(os.Args[2]) + + payloadLen, err := strconv.Atoi(os.Args[2]) + if err != nil { + logger.Fatalf("payload length \"%v\": %v", string(os.Args[2]), err) + } + payload := make([]byte, payloadLen) + if read, err := os.Stdin.Read(payload); read != len(payload) { + logger.Fatalf("Failed to read payload: %v, %v", read, err) + } var rows *sql.Rows if rows, err = db.Query(` -- 2.38.4