Эх сурвалжийг харах

fix #1119 and data race in timming tasks

Unknwon 9 жил өмнө
parent
commit
3d14e73fd8

+ 49 - 14
models/repo.go

@@ -17,6 +17,7 @@ import (
 	"regexp"
 	"sort"
 	"strings"
+	"sync"
 	"time"
 	"unicode/utf8"
 
@@ -1377,20 +1378,54 @@ func RewriteRepositoryUpdateHook() error {
 		})
 }
 
-var (
-	// Prevent duplicate running tasks.
-	isMirrorUpdating = false
-	isGitFscking     = false
-	isCheckingRepos  = false
+// statusPool represents a pool of status with true/false.
+type statusPool struct {
+	lock sync.RWMutex
+	pool map[string]bool
+}
+
+// Start sets value of given name to true in the pool.
+func (p *statusPool) Start(name string) {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+
+	p.pool[name] = true
+}
+
+// Stop sets value of given name to false in the pool.
+func (p *statusPool) Stop(name string) {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+
+	p.pool[name] = false
+}
+
+// IsRunning checks if value of given name is set to true in the pool.
+func (p *statusPool) IsRunning(name string) bool {
+	p.lock.RLock()
+	defer p.lock.RUnlock()
+
+	return p.pool[name]
+}
+
+// Prevent duplicate running tasks.
+var taskStatusPool = &statusPool{
+	pool: make(map[string]bool),
+}
+
+const (
+	_MIRROR_UPDATE = "mirror_update"
+	_GIT_FSCK      = "git_fsck"
+	_CHECK_REPOs   = "check_repos"
 )
 
 // MirrorUpdate checks and updates mirror repositories.
 func MirrorUpdate() {
-	if isMirrorUpdating {
+	if taskStatusPool.IsRunning(_MIRROR_UPDATE) {
 		return
 	}
-	isMirrorUpdating = true
-	defer func() { isMirrorUpdating = false }()
+	taskStatusPool.Start(_MIRROR_UPDATE)
+	defer taskStatusPool.Stop(_MIRROR_UPDATE)
 
 	log.Trace("Doing: MirrorUpdate")
 
@@ -1438,11 +1473,11 @@ func MirrorUpdate() {
 
 // GitFsck calls 'git fsck' to check repository health.
 func GitFsck() {
-	if isGitFscking {
+	if taskStatusPool.IsRunning(_GIT_FSCK) {
 		return
 	}
-	isGitFscking = true
-	defer func() { isGitFscking = false }()
+	taskStatusPool.Start(_GIT_FSCK)
+	defer taskStatusPool.Stop(_GIT_FSCK)
 
 	log.Trace("Doing: GitFsck")
 
@@ -1507,11 +1542,11 @@ func repoStatsCheck(checker *repoChecker) {
 }
 
 func CheckRepoStats() {
-	if isCheckingRepos {
+	if taskStatusPool.IsRunning(_CHECK_REPOs) {
 		return
 	}
-	isCheckingRepos = true
-	defer func() { isCheckingRepos = false }()
+	taskStatusPool.Start(_CHECK_REPOs)
+	defer taskStatusPool.Stop(_CHECK_REPOs)
 
 	log.Trace("Doing: CheckRepoStats")
 

+ 23 - 2
modules/git/tree.go

@@ -28,6 +28,28 @@ type Tree struct {
 	entriesParsed bool
 }
 
+var escapeChar = []byte("\\")
+
+func unescapeChars(in []byte) []byte {
+	if bytes.Index(in, escapeChar) == -1 {
+		return in
+	}
+
+	endIdx := len(in) - 1
+	isEscape := false
+	out := make([]byte, 0, endIdx+1)
+	for i := range in {
+		if in[i] == '\\' && i != endIdx {
+			isEscape = !isEscape
+			if isEscape {
+				continue
+			}
+		}
+		out = append(out, in[i])
+	}
+	return out
+}
+
 // Parse tree information from the (uncompressed) raw
 // data from the tree object.
 func parseTreeData(tree *Tree, data []byte) ([]*TreeEntry, error) {
@@ -74,8 +96,7 @@ func parseTreeData(tree *Tree, data []byte) ([]*TreeEntry, error) {
 
 		// In case entry name is surrounded by double quotes(it happens only in git-shell).
 		if entry.name[0] == '"' {
-			entry.name = string(data[pos+1 : pos+step-1])
-			entry.name = strings.Replace(entry.name, `\"`, `"`, -1)
+			entry.name = string(unescapeChars(data[pos+1 : pos+step-1]))
 		}
 
 		pos += step + 1

+ 3 - 0
routers/user/home.go

@@ -319,6 +319,9 @@ func Profile(ctx *middleware.Context) {
 	if uname == "favicon.ico" {
 		ctx.Redirect(setting.AppSubUrl + "/img/favicon.png")
 		return
+	} else if strings.HasSuffix(uname, ".png") {
+		ctx.Error(404)
+		return
 	}
 
 	isShowKeys := false