summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuinn Slack <[email protected]>2014-11-18 05:23:22 -0800
committerQuinn Slack <[email protected]>2014-12-08 11:52:35 -0800
commit3087e610fbceeeab8ad963a19aaac6fa61d10ccb (patch)
treea5d5035e54c68ccb6c6ae2108365343050e1eb31
parent520a0425c736c7d584d21d073b08a8735dd2464f (diff)
add script for checking thread locks in funcs that call MakeGitError
-rw-r--r--Makefile1
-rw-r--r--script/check-MakeGitError-thread-lock.go69
2 files changed, 70 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 4ecc8a4..3040857 100644
--- a/Makefile
+++ b/Makefile
@@ -4,6 +4,7 @@ build-libgit2:
./script/build-libgit2-static.sh
test: build-libgit2
+ go run script/check-MakeGitError-thread-lock.go
./script/with-static.sh go test ./...
install: build-libgit2
diff --git a/script/check-MakeGitError-thread-lock.go b/script/check-MakeGitError-thread-lock.go
new file mode 100644
index 0000000..10ab39f
--- /dev/null
+++ b/script/check-MakeGitError-thread-lock.go
@@ -0,0 +1,69 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/build"
+ "go/parser"
+ "go/printer"
+ "go/token"
+ "log"
+ "strings"
+)
+
+var (
+ fset = token.NewFileSet()
+)
+
+func main() {
+ log.SetFlags(0)
+
+ bpkg, err := build.ImportDir(".", 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ pkgs, err := parser.ParseDir(fset, bpkg.Dir, nil, 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ for _, pkg := range pkgs {
+ if err := checkPkg(pkg); err != nil {
+ log.Fatal(err)
+ }
+ }
+ if len(pkgs) == 0 {
+ log.Fatal("No packages to check.")
+ }
+}
+
+var ignoreViolationsInFunc = map[string]bool{
+ "MakeGitError": true,
+ "MakeGitError2": true,
+}
+
+func checkPkg(pkg *ast.Package) error {
+ var violations []string
+ ast.Inspect(pkg, func(node ast.Node) bool {
+ switch node := node.(type) {
+ case *ast.FuncDecl:
+ var b bytes.Buffer
+ if err := printer.Fprint(&b, fset, node); err != nil {
+ log.Fatal(err)
+ }
+ src := b.String()
+
+ if strings.Contains(src, "MakeGitError") && !strings.Contains(src, "runtime.LockOSThread()") && !strings.Contains(src, "defer runtime.UnlockOSThread()") && !ignoreViolationsInFunc[node.Name.Name] {
+ pos := fset.Position(node.Pos())
+ violations = append(violations, fmt.Sprintf("%s at %s:%d", node.Name.Name, pos.Filename, pos.Line))
+ }
+ }
+ return true
+ })
+ if len(violations) > 0 {
+ return fmt.Errorf("%d non-thread-locked calls to MakeGitError found. To fix, add the following to each func below that calls MakeGitError, before the cgo call that might produce the error:\n\n\truntime.LockOSThread()\n\tdefer runtime.UnlockOSThread()\n\n%s", len(violations), strings.Join(violations, "\n"))
+ }
+ return nil
+}