Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fatal error: concurrent map writes #15

Open
xtony77 opened this issue Feb 2, 2022 · 8 comments
Open

fatal error: concurrent map writes #15

xtony77 opened this issue Feb 2, 2022 · 8 comments
Labels
bug Something isn't working

Comments

@xtony77
Copy link

xtony77 commented Feb 2, 2022

If set the handler time.Sleep same as the timeout, there is a chance to reproduce this error!

api.GET("/test", timeout.New(
			timeout.WithTimeout(200*time.Microsecond),
			timeout.WithHandler(func(c *gin.Context) {
				time.Sleep(200*time.Microsecond)
				c.JSON(http.StatusOK, gin.H{
					"code": 200,
					"data": "",
				})
			}),
			timeout.WithResponse(func(c *gin.Context) {
				c.JSON(http.StatusRequestTimeout, gin.H{
					"code":    "408",
					"message": "test",
				})
			}),
		))

Here is gin panic code line:
https://github.com/gin-gonic/gin/blob/580e7da6eed01e2926de1240ec31f6473cd1a2af/render/render.go#L38

There is also a chance of combined http results:

{
    "code": 200,
    "data": ""
}{
    "code": "408",
    "message": "test"
}

I can't think of a solution at the moment, does anyone have any good ideas?

@appleboy
Copy link
Member

appleboy commented Feb 4, 2022

What is your version?

@xtony77
Copy link
Author

xtony77 commented Feb 4, 2022

github.com/gin-contrib/timeout v0.0.3-0.20220106074521-2cfe50edf125
github.com/gin-gonic/gin v1.7.2

@appleboy
Copy link
Member

@xtony77 I can't reproduce the issue

@xtony77
Copy link
Author

xtony77 commented Jun 24, 2022

I tried a few more times and still have a chance to reproduce the problem!
As you can see in the screenshot, although the http status code is 408, the http result is merged.

github.com/gin-gonic/gin v1.8.1
github.com/gin-contrib/timeout v0.0.3

截圖 2022-06-25 上午2 25 37

@appleboy
Copy link
Member

@xtony77 OK. I will take a look.

@KuanYuLai
Copy link

KuanYuLai commented Feb 25, 2023

I was able to reproduce the bug but the chance is very rare for me. However, when I change the sleep duration of the code: 200 response, the chance to produce the fatal error: concurrent map writes error is higher.

Code:

	r.GET("/timeout", timeout.New(timeout.WithTimeout(200*time.Microsecond),
		timeout.WithHandler(func(c *gin.Context) {
			time.Sleep(199 * time.Microsecond)
			c.JSON(http.StatusOK, gin.H{
				"code": 200,
				"data": "",
			})
		}),
		timeout.WithResponse(func(c *gin.Context) {
			c.JSON(http.StatusRequestTimeout, gin.H{
				"code":    408,
				"message": "test",
			})
		})))

Error:
image

@marko1777
Copy link

marko1777 commented Aug 23, 2023

if you use apach benchmark you can easily reproduce this issue
ab -n 3000 -c 500 localhost:8080/
image

func timeoutMiddleware() gin.HandlerFunc {
   return timeout.New(
   	timeout.WithTimeout(2*time.Second),
   	timeout.WithHandler(func(c *gin.Context) {
   		c.Next()
   	}),
   	timeout.WithResponse(testResponse),
   )
}

func main() {
   router := gin.Default()
   router.Use(timeoutMiddleware())
}

@x-lambda
Copy link

x-lambda commented Sep 19, 2023

// Header will get response headers
func (w *Writer) Header() http.Header {
	for i := 0; i < 100000; i++ {
		w.headers["a"] = []string{"b"}
	}

	return w.headers
}

Actually, I use for{} write map When call Header(), it's 100% panic.

This proves that 2 gotoutine are operating with header in parallel

@appleboy appleboy added the bug Something isn't working label Feb 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants