-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
cmd/go: deadlock occurs if GOCACHEPROG
program exits after receiving "close" command without sending response back
#70848
Comments
Addition: sending response to "close" command actually eliminates this issue. Program package main
import (
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"os"
)
var declareClose = flag.Bool("declare-close", false, "declare close command")
func main() {
flag.Parse()
enc := json.NewEncoder(os.Stdout)
dec := json.NewDecoder(os.Stdin)
// send handshake
cmds := []string{"get"}
if *declareClose {
cmds = append(cmds, "close")
}
if err := enc.Encode(Response{ID: 0, KnownCommands: cmds}); err != nil {
panic(err)
}
for {
var req Request
if err := dec.Decode(&req); err != nil {
if errors.Is(err, io.EOF) {
fmt.Fprintln(os.Stderr, "EOF bye!")
return
}
panic(err)
}
if req.Command == "close" {
if err := enc.Encode(Response{ID: req.ID}); err != nil {
panic(err)
}
fmt.Fprintln(os.Stderr, "close bye!")
return
}
if req.Command != "get" {
if err := enc.Encode(Response{ID: req.ID, Err: "unknown command"}); err != nil {
panic(err)
}
continue
}
if err := enc.Encode(Response{ID: req.ID, Miss: true}); err != nil {
panic(err)
}
}
}
type Request struct {
ID int
Command string
}
type Response struct {
ID int
Err string `json:",omitempty"`
KnownCommands []string `json:",omitempty"`
Miss bool `json:",omitempty"`
} Result: > GOCACHEPROG="$(pwd)/testcacheprog -declare-close" go install std
close bye! exit code 0 |
GOCACHEPROG
program exits after receiving "close" commandGOCACHEPROG
program exits after receiving "close" command without sending response back
@matloob @rsc @samthanawalla |
cc @bradfitz I think this is a bug. If we get an EOF (or any other error) reading the stdout of the cacheprog, we usually print an error if there are requests we haven't received responses for... unless we are mid-close. If we're mid-close, we quietly drop the error. The problem with that is that we then close all the channels we'd send the responses to, and the select waiting for the response from the close request's channel has no viable branches leading to our deadlock. There are a couple options for how to deal with this
|
Go version
go version devel go1.24-e39e965 Fri Dec 13 15:07:27 2024 -0800 linux/amd64
Output of
go env
in your module/workspace:What did you do?
I'm trying to play with
GOCACHEPROG
. I've compiled following codeusing
go build -o testcacheprog main.go
.And I'm trying to use resulting program like this
GOCACHEPROG="$(pwd)/testcacheprog" go build std"
and like thisGOCACHEPROG="$(pwd)/testcacheprog -declare-close" go build std"
.What did you see happen?
exit code 0
exit code 2
What did you expect to see?
exit code 0
exit code 0
The text was updated successfully, but these errors were encountered: