From 93ab90743d27f292eb7e8413e5ef1c6b10a65292 Mon Sep 17 00:00:00 2001
From: zeripath <art27@cantab.net>
Date: Wed, 25 May 2022 01:51:53 +0100
Subject: [PATCH] Prevent loop if there is an error in GetNotificationCount
 (#19799)

If the context is cancelled `.NotificationUnreadCount` in a template can
cause an infinite loop with `ctx.ServerError()` being called, which
creates a template that then calls `.NotificationUnreadCount` calling
`GetNotificationCount()` with the cancelled context resulting in an
error that calls `ctx.ServerError`... and so on...

This PR simply stops calling `ctx.ServerError` in the error handler code
for `.NotificationUnreadCount` as we have already started rendering and
so it is too late to call `ctx.ServerError`. Additionally we skip
logging the error if it's a context cancelled error.

Fix #19793

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
---
 routers/web/user/notification.go | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go
index 0b1789dcf8..9e658bcb14 100644
--- a/routers/web/user/notification.go
+++ b/routers/web/user/notification.go
@@ -5,6 +5,7 @@
 package user
 
 import (
+	goctx "context"
 	"errors"
 	"fmt"
 	"net/http"
@@ -14,6 +15,7 @@ import (
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/base"
 	"code.gitea.io/gitea/modules/context"
+	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/structs"
 )
@@ -36,7 +38,9 @@ func GetNotificationCount(c *context.Context) {
 	c.Data["NotificationUnreadCount"] = func() int64 {
 		count, err := models.GetNotificationCount(c, c.Doer, models.NotificationStatusUnread)
 		if err != nil {
-			c.ServerError("GetNotificationCount", err)
+			if err != goctx.Canceled {
+				log.Error("Unable to GetNotificationCount for user:%-v: %v", c.Doer, err)
+			}
 			return -1
 		}