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: ListenUnixgram's ReadFrom always fails "address family not supported by protocol" #3875

Closed
gopherbot opened this issue Jul 28, 2012 · 13 comments
Milestone

Comments

@gopherbot
Copy link

by jls@semicomplete.com:

What steps will reproduce the problem?

* Code:
https://github.com/jordansissel/experiments/blob/master/go/unixgram-broken/unixgram_test.go
* rm /tmp/example.sock (used by this program)
* go test unixgram_test.go

What is the expected output?

Some kind of passing indication :)

What do you see instead?

% go test unixgram_test.go
--- FAIL: TestListenUnixgramReadFrom (0.00 seconds)
        unixgram_test.go:54: UnixConn.ReadFromfailed: read unixgram /tmp/example.sock: address family not supported by protocol
FAIL
FAIL    command-line-arguments  0.063s


Which compiler are you using (5g, 6g, 8g, gccgo)?

6g

Which operating system are you using?

linux

Which version are you using?  (run 'go version')

go version go1.0.1

Please provide any additional information below.

* strace shows go successfully calling recvfrom(2), yet an errno 97 is reported as well:

% strace -fe trace=recvfrom go test unixgram_test.go
[pid  5981] recvfrom(3, "Hello world", 100, 0, {sa_family=AF_UNSPEC,
sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, [0]) = 11

* recvfrom(2) on unix datagram sockets yields no peer address/origin of the packet. See
example C code here showing the same behavior:

https://github.com/jordansissel/experiments/blob/master/c/sockets/unixdatagram.c - run,
send a message to the socket, and output is:

% ./a.out /tmp/example
client addr type, len: 0, 0
Got: '<5>Jul 28 01:06:48 jls: hello world

I tried to dig into the Go code, but it's a bit confusing. The problem seems to live in
net/fd.go ReadFrom's syscall.Recvfrom invocation, or alternately in syscall.Recvfrom's
implementation, perhaps? It's hard to really say - in C, errno is not set, yet in Go,
the errno-equivalent is set after the recvfrom syscall returns. Any ideas?

It's worth noting that syscall.Recvfrom, while reporting an error, still updates the
byte slice (p) and length (n) with the datagram payload.
@gopherbot
Copy link
Author

Comment 1 by jls@semicomplete.com:

If I patch net/unixgram_posix.go to have ListenUnixgram return a UnixConn, I can call
ReadFrom on it and both a non-zero length and an error are returned.
If the original Go net package is used, ReadFrom on the UDPConn returns zero length and
an error.

@gopherbot
Copy link
Author

Comment 2 by jls@semicomplete.com:

I was able to find a few mailing list threads with no answers. Mostly folks reporting
this problem and others asking for proof. I hope this ticket suffices for proof.
* https://groups.google.com/d/msg/golang-nuts/bRvYw6-9gyU/uLMC6VczGWMJ
* https://groups.google.com/d/msg/golang-nuts/fTh-TzjMtQA/lYggB9M4za8J

@rsc
Copy link
Contributor

rsc commented Sep 12, 2012

Comment 3:

Labels changed: added priority-later, removed priority-triage.

Status changed to Accepted.

@rsc
Copy link
Contributor

rsc commented Sep 12, 2012

Comment 4:

Labels changed: added go1.1maybe.

@mikioh
Copy link
Contributor

mikioh commented Nov 12, 2012

Comment 5:

I must confess, I have no clue what ListenUnixgram is.
Doc says:
// ListenUnixgram listens for incoming Unix datagram packets addressed to the
// local address laddr.  The returned connection c's ReadFrom
// and WriteTo methods can be used to receive and send UDP
// packets with per-packet addressing.  The network net must be "unixgram".
func ListenUnixgram(net string, laddr *UnixAddr) (*UDPConn, error)
maybe the original API designers intended to make a protocol bridge 
btw UDP and Unix or underlying local file read/write, not sure.
It seems that the latter is already available by FileConn, FileListener 
and FilePacketConn API. The former would be a tough work. So it looks 
this API is a design orphan and perhaps should be obsoleted in the future
release.

@remyoudompheng
Copy link
Contributor

Comment 6:

Unix sockets have two kinds: SOCK_STREAM (similar to TCP) and SOCK_DGRAM (similar to
UDP). unixgram is the second kind.

@mikioh
Copy link
Contributor

mikioh commented Nov 12, 2012

Comment 7:

Hi Remy,
What I don't understand is, how is it possible to make a
following combination.
a) listens for incoming Unix datagram packets addressed 
to the local address laddr.
This happens in Unix domain namespace, perhaps.
b) The returned connection c's ReadFrom and WriteTo 
methods can be used to receive and send UDP packets
with per-packet addressing.
This happens in either UDP domain namespace or Unix
domain space, or both?

@gopherbot
Copy link
Author

Comment 8 by jls@semicomplete.com:

I think my general bug report is best summarized as "cannot use unix datagram sockets in
Go"
Speculating, I believe the "UDP" text in the Unixgram documents are a typo. The problem
isn't the documentation strictly, the problem is the inability to read from unix
datagram sockets - unless there is an alternative api available for this?

@mikioh
Copy link
Contributor

mikioh commented Nov 12, 2012

Comment 9:

> an alternative api available for this?
I think those ReadFrom/ReadFromUnix/WriteTo/WriteToUnix 
methods UnixConn might be alternatives. Please take a look 
at tip, net/packetconn_test.go and net/protoconn_test.go 
describe simple use cases.

@gopherbot
Copy link
Author

Comment 10 by jls@semicomplete.com:

Summarizing: UnixConn doesn't work because it tries to connect(2).  ListenUnix doesn't
work because it tries to listen(2). ListenUnixgram doesn't work because it provides a
UDPConn which, on ReadFrom() rejects Unix address families and there is no
UDPConn.ReadFromUnix() 
UnixConn from DialUnix doesn't work for reading unixgram data, as 'DialUnix' tries to
connect, which is not correct for 'reading' datagrams from a unix domain socket -
strace output:
[pid  5847] socket(PF_FILE, SOCK_DGRAM, 0) = 3
[pid  5847] connect(3, {sa_family=AF_FILE, sun_path="/tmp/example.sock"}, 20) = -1
ECONNREFUSED (Connection refused)
on the flipside, net.ListenUnixgram does the correct thing:
[pid  6312] socket(PF_FILE, SOCK_DGRAM, 0) = 3
[pid  6312] bind(3, {sa_family=AF_FILE, sun_path="/tmp/example.sock"}, 20) = 0
It's just that you can't read from it due to assumptions of address families (likely due
to ListenUnixgram returning a UDPCon).
ListenUnix gives a UnixListener which requires you call AcceptUnix(), which fails
because that calls listen(2) which fails on unix datagram sockets:
[pid  7652] socket(PF_FILE, SOCK_DGRAM, 0) = 3
[pid  7652] bind(3, {sa_family=AF_FILE, sun_path="/tmp/example.sock"}, 20) = 0
[pid  7652] listen(3, 128)              = -1 EOPNOTSUPP (Operation not supported)

@mikioh
Copy link
Contributor

mikioh commented Nov 12, 2012

Comment 11:

Hi jls,
Thanks for your comments #10.
I can't say "not correct" because that's user's choice; named unix 
domain sockets or unnamed unix domain sockets.
It looks like current net/unixsock stuff supports named unix domain 
sockets only, unfortunately. So please file a new issue related to your 
comment #10; you need an unmaed unix domain socket or whatever.
Also feel free to send a patch because I'm not a right person to fix u
nix domain socket stuff.
<http://golang.org/doc/contribute.html>;
So let's focus on wrt ListenUnixgram here, whether it's typo or not.
Thanks.

@mikioh
Copy link
Contributor

mikioh commented Nov 12, 2012

@mikioh
Copy link
Contributor

mikioh commented Dec 16, 2012

Comment 13:

This issue was closed by revision 0d19725.

Status changed to Fixed.

@rsc rsc added this to the Go1.1 milestone Apr 14, 2015
@rsc rsc removed the go1.1maybe label Apr 14, 2015
@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants