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: ListenAndServe example deadlocks in playground #50045

Open
thaJeztah opened this issue Dec 8, 2021 · 6 comments
Open

net/http: ListenAndServe example deadlocks in playground #50045

thaJeztah opened this issue Dec 8, 2021 · 6 comments
Labels
Documentation NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@thaJeztah
Copy link
Contributor

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

$ go version
go1.17.4

Does this issue reproduce with the latest release?

Yes

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

go env Output
$ go env

What did you do?

Run the go playground example for net/http.ListenAndServe() (https://play.golang.org/p/j01H9doftSz)

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [IO wait]:
internal/poll.runtime_pollWait(0x7f004b011eb8, 0x72)
	/usr/local/go-faketime/src/runtime/netpoll.go:234 +0x89
internal/poll.(*pollDesc).wait(0xc000134000, 0x4, 0x0)
	/usr/local/go-faketime/src/internal/poll/fd_poll_runtime.go:84 +0x32
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/go-faketime/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).Accept(0xc000134000)
	/usr/local/go-faketime/src/internal/poll/fd_unix.go:402 +0x22c
net.(*netFD).accept(0xc000134000)
	/usr/local/go-faketime/src/net/fd_unix.go:173 +0x35
net.(*TCPListener).accept(0xc00000c0f0)
	/usr/local/go-faketime/src/net/tcpsock_posix.go:140 +0x28
net.(*TCPListener).Accept(0xc00000c0f0)
	/usr/local/go-faketime/src/net/tcpsock.go:262 +0x3d
net/http.(*Server).Serve(0xc000132000, {0x6962b0, 0xc00000c0f0})
	/usr/local/go-faketime/src/net/http/server.go:3002 +0x394
net/http.(*Server).ListenAndServe(0xc000132000)
	/usr/local/go-faketime/src/net/http/server.go:2931 +0x7d
net/http.ListenAndServe(...)
	/usr/local/go-faketime/src/net/http/server.go:3185
main.main()
	/tmp/sandbox528359240/prog.go:20 +0xb4

Program exited.

What did you expect to see?

Hello, world!

What did you see instead?

See above

@seankhliao seankhliao changed the title go playground: net/http.ListenAndServe() example produces a deadlock net/http: ListenAndServe example deadlocks in playground Dec 8, 2021
@seankhliao seankhliao added Documentation NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Dec 8, 2021
@bcmills
Copy link
Member

bcmills commented Dec 10, 2021

It's, uh... not wrong? If you assume that the only connections that will be accepted come from the program itself (which AFAICT is a valid assumption in the faked world of the Playground), then it really is deadlocked.

Shoving the server into the background and making an actual call to it seems to work:
https://go.dev/play/p/PCryrIf6hEw

@thaJeztah
Copy link
Contributor Author

Thanks for looking!

So the TL;DR of this was that I was chatting with someone on my phone, and thought http.ListenAndServe() was a nice example to show "this is one of the things that make Go nice!". Then clicked the "run example", and saw the ugly trace (which likely wasn't the intent of that example, and very likely will confuse users).

Your updated example looks good (perhaps even better, as it's a more complete example); slightly concerned if the added complexity will distract from the http.ListenAndServe() topic itself.

@bcmills
Copy link
Member

bcmills commented Dec 10, 2021

FWIW, I think that update may actually be racy. (I'm not sure what it happens to do if the http.Get goroutine executes before the ListenAndServe goroutine has opened the socket.)

If you're going to use ListenAndServe for an application that has actual tests, you'll probably have to write a spin-loop that waits for the server to come up before starting the tests. IMO it's much more ergonomic to just use net.Listen and http.Serve separately, so that you can establish the Listener before starting the requests to it.

@bcmills
Copy link
Member

bcmills commented Dec 10, 2021

A more appropriate example is probably something like https://go.dev/play/p/UFd9OAIjx_B.

@seankhliao
Copy link
Member

that's almost identical to the "Http Server" example in the playground dropdown

@bcmills
Copy link
Member

bcmills commented Dec 10, 2021

So it is. Perfect!

Then maybe we should replace the ListenAndServe example with a deprecation notice. 😁

@seankhliao seankhliao added this to the Unplanned milestone Aug 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

3 participants