-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Run basic diagnostics when scandeps server fails to boot up
The diagnostic is to basically start a dummy RPC server at the UDS address and see if it can work. Also added code to remove the socket file at the UDS address before starting up scandeps_server TESTED=tested on windows, added unit tests Bug: b/378041961 Change-Id: Ifb651f2ac1072a73eea7060150ec394367d3a934 GitOrigin-RevId: a9fe0e3b9cedb79980e7a27f813e8be6a290d85b
- Loading branch information
1 parent
ed0afed
commit 3f1fd71
Showing
6 changed files
with
228 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") | ||
|
||
go_library( | ||
name = "diagnostics", | ||
srcs = [ | ||
"diagnostics.go", | ||
"simpleclientserver.go", | ||
], | ||
importpath = "github.com/bazelbuild/reclient/internal/pkg/diagnostics", | ||
visibility = ["//:__subpackages__"], | ||
deps = ["@com_github_golang_glog//:glog"], | ||
) | ||
|
||
go_test( | ||
name = "diagnostics_test", | ||
srcs = ["simpleclientserver_test.go"], | ||
embed = [":diagnostics"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Package diagnostics is used to provide diagnostic functionality to triage | ||
// problems with reclient during failure scenarios. | ||
package diagnostics | ||
|
||
import ( | ||
"context" | ||
|
||
log "github.com/golang/glog" | ||
) | ||
|
||
// DiagnosticInputs struct holds key state necessary for diagnostics to run. | ||
type DiagnosticInputs struct { | ||
UDSAddr string | ||
} | ||
|
||
// Run runs the diagnostics. | ||
func Run(ctx context.Context, in *DiagnosticInputs) { | ||
if err := CheckUDSAddrWorks(ctx, in.UDSAddr); err != nil { | ||
log.Errorf("DIAGNOSTIC_ERROR: UDS address check for %v had errors: %v", in.UDSAddr, err) | ||
} else { | ||
log.Infof("DIAGNOSTIC_SUCCESS: UDS address %v works with toy RPC server", in.UDSAddr) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package diagnostics | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net" | ||
"net/rpc" | ||
"os" | ||
"strings" | ||
|
||
log "github.com/golang/glog" | ||
) | ||
|
||
// HelloService is a simple service to provide a HelloWorld RPC. | ||
type HelloService struct{} | ||
|
||
// HelloRequest identifies the hello world request. | ||
type HelloRequest struct{} | ||
|
||
// HelloResponse identifies the hello world response. | ||
type HelloResponse struct { | ||
Message string | ||
} | ||
|
||
// HelloWorld is the RPC method that returns a hello world response. | ||
func (s *HelloService) HelloWorld(req *HelloRequest, res *HelloResponse) error { | ||
res.Message = "Hello, world!" | ||
return nil | ||
} | ||
|
||
// CheckUDSAddrWorks checks if we are able to start a basic RPC | ||
// server at the given UDS address. Useful to diagnost scandeps_server | ||
// startup timeout issues. | ||
func CheckUDSAddrWorks(ctx context.Context, addr string) error { | ||
if strings.HasPrefix(addr, "unix://") { | ||
addr = strings.ReplaceAll(addr, "unix://", "") | ||
} else if strings.HasPrefix(addr, "unix:") { | ||
addr = strings.ReplaceAll(addr, "unix:", "") | ||
} else { | ||
return fmt.Errorf("addr must begin with a unix:// or unix: prefix: %v", addr) | ||
} | ||
os.RemoveAll(addr) | ||
|
||
serverStarted := make(chan bool, 1) | ||
clientComplete := make(chan bool, 1) | ||
errs := make(chan error, 1) | ||
var listener net.Listener | ||
|
||
go func() { | ||
helloService := new(HelloService) | ||
err := rpc.Register(helloService) | ||
if err != nil { | ||
errs <- fmt.Errorf("error registering service: %v", err) | ||
return | ||
} | ||
|
||
listener, err = net.Listen("unix", addr) | ||
if err != nil { | ||
errs <- fmt.Errorf("listener error: %v", err) | ||
return | ||
} | ||
|
||
log.Infof("Diagnostic server listening on UNIX socket: %v", addr) | ||
serverStarted <- true | ||
rpc.Accept(listener) | ||
}() | ||
select { | ||
case <-ctx.Done(): | ||
return fmt.Errorf("context timeout reached in CheckUDSAddrWorks(%v)", addr) | ||
|
||
case <-serverStarted: | ||
break | ||
|
||
case err := <-errs: | ||
return fmt.Errorf("failed to start RPC server at %v: %v", addr, err) | ||
} | ||
|
||
errs = make(chan error, 1) | ||
go func() { | ||
defer func() { | ||
clientComplete <- true | ||
}() | ||
client, err := rpc.Dial("unix", addr) | ||
if err != nil { | ||
errs <- fmt.Errorf("error connecting to server: %v", err) | ||
return | ||
} | ||
defer client.Close() | ||
|
||
req := &HelloRequest{} | ||
res := &HelloResponse{} | ||
|
||
err = client.Call("HelloService.HelloWorld", req, res) | ||
if err != nil { | ||
errs <- fmt.Errorf("error calling HelloWorld: %v", err) | ||
} | ||
}() | ||
log.V(1).Infof("DIAGNOSTICS: Waiting for client-server communication on address %v", addr) | ||
select { | ||
case <-ctx.Done(): | ||
return fmt.Errorf("context timeout reached in CheckUDSAddrWorks(%v)", addr) | ||
|
||
case <-clientComplete: | ||
break | ||
|
||
case err := <-errs: | ||
return fmt.Errorf("failed to talk to RPC server at %v: %v", addr, err) | ||
} | ||
listener.Close() | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package diagnostics | ||
|
||
import ( | ||
"context" | ||
"os" | ||
"path/filepath" | ||
"runtime" | ||
"testing" | ||
) | ||
|
||
func TestCheckUDSAddrWorks(t *testing.T) { | ||
var addr string | ||
if runtime.GOOS == "windows" { | ||
addr = "unix:" + filepath.Join(os.TempDir(), "test.sock") | ||
} else { | ||
addr = "unix://" + filepath.Join(os.TempDir(), "test.sock") | ||
} | ||
|
||
if err := CheckUDSAddrWorks(context.Background(), addr); err != nil { | ||
t.Errorf("CheckUDSAddrWorks(%v) failed: %v", addr, err) | ||
} | ||
} | ||
func TestCheckUDSAddrWorks_InvalidAddress(t *testing.T) { | ||
var addr string | ||
if runtime.GOOS == "windows" { | ||
addr = "unix:X:\\tmp\\test.sock" | ||
} else { | ||
addr = "unix:///rooooot/test.sock" | ||
} | ||
|
||
if err := CheckUDSAddrWorks(context.Background(), addr); err == nil { | ||
t.Errorf("CheckUDSAddrWorks(%v) expected error but succeeded", addr) | ||
} | ||
} |