Skip to content

Commit 53f9c3f

Browse files
committed
Defer closing the gitrepo until the end of the wrapped context functions (go-gitea#15653)
Backport go-gitea#15653 There was a mistake in go-gitea#15372 where deferral of gitrepo close occurs before it should. This PR fixes this. Signed-off-by: Andrew Thornton <art27@cantab.net>
1 parent f9b1fac commit 53f9c3f

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

modules/context/repo.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package context
77

88
import (
9+
"context"
910
"fmt"
1011
"io/ioutil"
1112
"net/url"
@@ -393,7 +394,7 @@ func RepoIDAssignment() func(ctx *Context) {
393394
}
394395

395396
// RepoAssignment returns a middleware to handle repository assignment
396-
func RepoAssignment(ctx *Context) {
397+
func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
397398
var (
398399
owner *models.User
399400
err error
@@ -529,12 +530,12 @@ func RepoAssignment(ctx *Context) {
529530
ctx.Repo.GitRepo = gitRepo
530531

531532
// We opened it, we should close it
532-
defer func() {
533+
cancel = func() {
533534
// If it's been set to nil then assume someone else has closed it.
534535
if ctx.Repo.GitRepo != nil {
535536
ctx.Repo.GitRepo.Close()
536537
}
537-
}()
538+
}
538539

539540
// Stop at this point when the repo is empty.
540541
if ctx.Repo.Repository.IsEmpty {
@@ -619,6 +620,7 @@ func RepoAssignment(ctx *Context) {
619620
ctx.Data["GoDocDirectory"] = prefix + "{/dir}"
620621
ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}"
621622
}
623+
return
622624
}
623625

624626
// RepoRefType type of repo reference
@@ -643,7 +645,7 @@ const (
643645

644646
// RepoRef handles repository reference names when the ref name is not
645647
// explicitly given
646-
func RepoRef() func(*Context) {
648+
func RepoRef() func(*Context) context.CancelFunc {
647649
// since no ref name is explicitly specified, ok to just use branch
648650
return RepoRefByType(RepoRefBranch)
649651
}
@@ -722,8 +724,8 @@ func getRefName(ctx *Context, pathType RepoRefType) string {
722724

723725
// RepoRefByType handles repository reference name for a specific type
724726
// of repository reference
725-
func RepoRefByType(refType RepoRefType) func(*Context) {
726-
return func(ctx *Context) {
727+
func RepoRefByType(refType RepoRefType) func(*Context) context.CancelFunc {
728+
return func(ctx *Context) (cancel context.CancelFunc) {
727729
// Empty repository does not have reference information.
728730
if ctx.Repo.Repository.IsEmpty {
729731
return
@@ -742,12 +744,12 @@ func RepoRefByType(refType RepoRefType) func(*Context) {
742744
return
743745
}
744746
// We opened it, we should close it
745-
defer func() {
747+
cancel = func() {
746748
// If it's been set to nil then assume someone else has closed it.
747749
if ctx.Repo.GitRepo != nil {
748750
ctx.Repo.GitRepo.Close()
749751
}
750-
}()
752+
}
751753
}
752754

753755
// Get default branch.
@@ -841,6 +843,7 @@ func RepoRefByType(refType RepoRefType) func(*Context) {
841843
return
842844
}
843845
ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
846+
return
844847
}
845848
}
846849

modules/web/route.go

+30
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package web
66

77
import (
8+
goctx "context"
89
"fmt"
910
"net/http"
1011
"reflect"
@@ -27,6 +28,7 @@ func Wrap(handlers ...interface{}) http.HandlerFunc {
2728
switch t := handler.(type) {
2829
case http.HandlerFunc, func(http.ResponseWriter, *http.Request),
2930
func(ctx *context.Context),
31+
func(ctx *context.Context) goctx.CancelFunc,
3032
func(*context.APIContext),
3133
func(*context.PrivateContext),
3234
func(http.Handler) http.Handler:
@@ -48,6 +50,15 @@ func Wrap(handlers ...interface{}) http.HandlerFunc {
4850
if r, ok := resp.(context.ResponseWriter); ok && r.Status() > 0 {
4951
return
5052
}
53+
case func(ctx *context.Context) goctx.CancelFunc:
54+
ctx := context.GetContext(req)
55+
cancel := t(ctx)
56+
if cancel != nil {
57+
defer cancel()
58+
}
59+
if ctx.Written() {
60+
return
61+
}
5162
case func(ctx *context.Context):
5263
ctx := context.GetContext(req)
5364
t(ctx)
@@ -94,6 +105,23 @@ func Middle(f func(ctx *context.Context)) func(netx http.Handler) http.Handler {
94105
}
95106
}
96107

108+
// MiddleCancel wrap a context function as a chi middleware
109+
func MiddleCancel(f func(ctx *context.Context) goctx.CancelFunc) func(netx http.Handler) http.Handler {
110+
return func(next http.Handler) http.Handler {
111+
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
112+
ctx := context.GetContext(req)
113+
cancel := f(ctx)
114+
if cancel != nil {
115+
defer cancel()
116+
}
117+
if ctx.Written() {
118+
return
119+
}
120+
next.ServeHTTP(ctx.Resp, ctx.Req)
121+
})
122+
}
123+
}
124+
97125
// MiddleAPI wrap a context function as a chi middleware
98126
func MiddleAPI(f func(ctx *context.APIContext)) func(netx http.Handler) http.Handler {
99127
return func(next http.Handler) http.Handler {
@@ -163,6 +191,8 @@ func (r *Route) Use(middlewares ...interface{}) {
163191
r.R.Use(t)
164192
case func(*context.Context):
165193
r.R.Use(Middle(t))
194+
case func(*context.Context) goctx.CancelFunc:
195+
r.R.Use(MiddleCancel(t))
166196
case func(*context.APIContext):
167197
r.R.Use(MiddleAPI(t))
168198
default:

0 commit comments

Comments
 (0)