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

net/http: HandleFunc block #23141

Closed
xfarret opened this issue Dec 14, 2017 · 10 comments

Comments

Projects
None yet
5 participants
@xfarret
Copy link

commented Dec 14, 2017

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.9.2 darwin/amd64

Does this issue reproduce with the latest release?

I suppose it is the last release

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"

What did you do?

package main

var indice = 0
var thnb = 0

func Hello(w http.ResponseWriter, r *http.Request) {
indice++
thnb ++
var i = indice
r.ParseForm()
if indice == 1 {
time.Sleep(40 * time.Second)
} else {
indice = 0
}
m := fmt.Sprintf("Hello from Golang with indice: %d, thread: %d", i, thnb)
json.NewEncoder(w).Encode(m)
}

func main() {
http.HandleFunc("/hello", Hello)
s := &http.Server{
Addr: ":8000",
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
//MaxHeaderBytes: 1 << 20,
}
}

What did you expect to see?

I expected that the first request doesn't block the second one launch at the same time.

What did you see instead?

The first request block the second one during its sleep process when I invoke the url : http://127.0.0.1/hello
But if I add parameters to the URL like:

I don't understand what's the difference and why the handleFunc blocks.

Thanks for your answer

@mvdan

This comment has been minimized.

Copy link
Member

commented Dec 14, 2017

The Go issue tracker is for bugs and feature proposals. This sounds like a question, and doesn't clarify where the bug in Go is, so I suggest that you use one of the discussion forums instead: https://golang.org/wiki/Questions

@mvdan mvdan closed this Dec 14, 2017

@bradfitz

This comment has been minimized.

Copy link
Member

commented Dec 14, 2017

It also has a data race. It's not safe to read/write indice without synchronization.

@xfarret

This comment has been minimized.

Copy link
Author

commented Dec 14, 2017

indice was just an example. You're right bradfitz.
I suppose mvdan it is a bug, not a question anymore. I surprise to see two distincts behavior.
Can you consider my request not as a question but as an issue ?

@bradfitz

This comment has been minimized.

Copy link
Member

commented Dec 14, 2017

If this is a bug report, it needs to be delivered like one.

Remove unneeded code and give complete details.

For instance, what does "When I invoke the url" mean? What is your HTTP client? Is that also Go (code?), or is that a browser (which?) ?

Are the ReadTimeout or WriteTimeout relevant? If so, both, neither, just one?

Is the ParseForm relevant?

etc.

@xfarret

This comment has been minimized.

Copy link
Author

commented Dec 15, 2017

Hi, here is a new sample with the same behavior.

main.go
package main

import (
"fmt"
"log"
"net/http"
"proj/api"
)

func main() {
http.HandleFunc("/hello", GetOnly(api.Hello))
s := &http.Server{Addr: ":8000"}
log.Fatal(s.ListenAndServe())
}

endpoints.go
package api

import (
"fmt"
"net/http"
"time"
"proj/tictac"
)

func Hello(w http.ResponseWriter, r *http.Request) {
var indice = tictac.GetIndice()
if indice % 2 != 0 {
time.Sleep(10 * time.Second)
}
message := fmt.Sprintf("Hello from Golang with indice: %d", indice)
fmt.Fprintf(w, message)
}

indice.go
package tictac

var indice = 0

func GetIndice() int {
val := make(chan int)
go inc(val)
return <- val
}

func inc(val chan int) {
indice ++
val <- indice
}

As you can see indice is protected for concurrent access.

  • How to reproduce the trouble:
    I use a web browser such as chrome version 63 and firefox version 57.
    I open 3 tabs with the same url: http://127.0.0.1/hello
    Then I start each of them, the first, the second and the third.

  • Result:
    The first tab: indice value is equal to one, then a sleep is made
    The second tab: the process is blocked as long as the first process is not finished. As soon as the first process finished the second is process without sleep due to modulo 2
    The third tab: the process is blocked by the second one. As soon as the second process is finished the process begin, a sleep is made. For this process I expect a ime equal to the value of the sleep, but in reallity time is the sum of the 2 other process + its sleep value.

I hope my explaination is more specific.

@davecheney

This comment has been minimized.

Copy link
Contributor

commented Dec 15, 2017

@xfarret

This comment has been minimized.

Copy link
Author

commented Dec 15, 2017

Thank for your advise. I start my program with the race detector. Then no report are displayed. I suppose that there is no data race in my code. Am I right ? (this is my second try with Go ...)

@davecheney

This comment has been minimized.

Copy link
Contributor

commented Dec 15, 2017

@xfarret

This comment has been minimized.

Copy link
Author

commented Dec 15, 2017

If I understand the documentation indice is protected by the channel because it is a synchronous access.
Another curious way is if I add a parameter for each tab the behavior change.
Tab 1: http://127.0.0.1/hello?param=1
Tab 2: http://127.0.0.1/hello?param=2
Tab 3: http://127.0.0.1/hello?param=3
With this url tab 1 is waiting during its sleep time, tab 2 is executed without waiting the tab 1 execution, same for tab 3

Strange isn't it ? This is why I don't suppose there's a data race in accessing indice variable. But may be I'm wrong ...

@davecheney

This comment has been minimized.

Copy link
Contributor

commented Dec 15, 2017

@mikioh mikioh changed the title HandleFunc block net/http: HandleFunc block Jan 5, 2018

@golang golang locked and limited conversation to collaborators Jan 5, 2019

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.