net/http: HandleFunc block #23141
net/http: HandleFunc block #23141
Comments
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 |
It also has a data race. It's not safe to read/write |
indice was just an example. You're right bradfitz. |
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. |
Hi, here is a new sample with the same behavior. main.go import ( func main() { endpoints.go import ( func Hello(w http.ResponseWriter, r *http.Request) { indice.go var indice = 0 func GetIndice() int { func inc(val chan int) { As you can see indice is protected for concurrent access.
I hope my explaination is more specific. |
Please run your program with the race detector, there is a possible data race in the tictac package.
… On 15 Dec 2017, at 21:47, xf73 ***@***.***> wrote:
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.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
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 ...) |
I believe the data race is here
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
}
indice is a package level variable, it is not safe to call GetIndice more
than once.
…On Fri, Dec 15, 2017 at 11:25 PM, xf73 ***@***.***> wrote:
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 ...)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#23141 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAAcA96hbWj828awgvVoi3VFRCG-2oPWks5tAmVNgaJpZM4RCn58>
.
|
If I understand the documentation indice is protected by the channel because it is a synchronous access. 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 ... |
Why don’t you try using a lock and see if that fixes your problem?
… On 15 Dec 2017, at 23:42, xf73 ***@***.***> wrote:
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 ...
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
|
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:
then the behavior is what I was expecting.
I don't understand what's the difference and why the handleFunc blocks.
Thanks for your answer
The text was updated successfully, but these errors were encountered: