Skip to content

Commit 5726498

Browse files
ianlancetaylorgopherbot
authored andcommitted
unix: in Linux sendmsgN actually send one normal byte
A bug in CL 412497 caused us to set up an iovec for a dummy byte but fail to use it Fixes golang/go#56384 Change-Id: If56fea5c47e5c6fac92f9707d4c3dd78f7999a65 Reviewed-on: https://go-review.googlesource.com/c/sys/+/445255 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Tobias Klauser <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]>
1 parent 95e765b commit 5726498

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

unix/syscall_linux.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,6 +1554,7 @@ func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Sockle
15541554
var iova [1]Iovec
15551555
iova[0].Base = &dummy
15561556
iova[0].SetLen(1)
1557+
iov = iova[:]
15571558
}
15581559
}
15591560
msg.Control = &oob[0]

unix/syscall_unix_test.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,102 @@ func TestSendmsgBuffers(t *testing.T) {
10151015
}
10161016
}
10171017

1018+
// Issue 56384.
1019+
func TestRecvmsgControl(t *testing.T) {
1020+
switch runtime.GOOS {
1021+
case "solaris", "illumos":
1022+
// Test fails on Solaris, saying
1023+
// "got 0 control messages, want 1".
1024+
// Not sure why; Solaris recvmsg man page says
1025+
// "For processes on the same host, recvmsg() can be
1026+
// used to receive a file descriptor from another
1027+
// process, but it cannot receive ancillary data."
1028+
t.Skipf("skipping on %s", runtime.GOOS)
1029+
}
1030+
1031+
fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM, 0)
1032+
if err != nil {
1033+
t.Fatal(err)
1034+
}
1035+
defer unix.Close(fds[0])
1036+
defer unix.Close(fds[1])
1037+
1038+
const payload = "hello"
1039+
1040+
// Start a goroutine that sends a control message followed by
1041+
// a payload on fds[1].
1042+
go func() {
1043+
f, err := os.Create(filepath.Join(t.TempDir(), "file"))
1044+
if err != nil {
1045+
t.Error(err)
1046+
return
1047+
}
1048+
defer f.Close()
1049+
1050+
rc, err := f.SyscallConn()
1051+
if err != nil {
1052+
t.Error(err)
1053+
return
1054+
}
1055+
var rights []byte
1056+
err = rc.Control(func(fd uintptr) {
1057+
rights = unix.UnixRights(int(fd))
1058+
})
1059+
if err != nil {
1060+
t.Error(err)
1061+
return
1062+
}
1063+
1064+
_, err = unix.SendmsgN(fds[1], nil, rights, nil, 0)
1065+
if err != nil {
1066+
t.Error(err)
1067+
}
1068+
if _, err := unix.Write(fds[1], []byte(payload)); err != nil {
1069+
t.Error(err)
1070+
}
1071+
}()
1072+
1073+
// Read the control message sent by the goroutine. The
1074+
// goroutine writes to fds[1], we read from fds[0].
1075+
1076+
cbuf := make([]byte, unix.CmsgSpace(4))
1077+
_, cn, _, _, err := unix.Recvmsg(fds[0], nil, cbuf, 0)
1078+
if err != nil {
1079+
t.Fatal(err)
1080+
}
1081+
cbuf = cbuf[:cn]
1082+
1083+
// Read the payload sent by the goroutine.
1084+
1085+
buf := make([]byte, len(payload))
1086+
n, err := unix.Read(fds[0], buf)
1087+
if err != nil {
1088+
t.Fatal(err)
1089+
}
1090+
buf = buf[:n]
1091+
if payload != string(buf) {
1092+
t.Errorf("read payload %q, want %q", buf, payload)
1093+
}
1094+
1095+
// Check the control message.
1096+
1097+
cmsgs, err := unix.ParseSocketControlMessage(cbuf)
1098+
if err != nil {
1099+
t.Fatal(err)
1100+
}
1101+
if len(cmsgs) != 1 {
1102+
t.Fatalf("got %d control messages, want 1", len(cmsgs))
1103+
}
1104+
cfds, err := unix.ParseUnixRights(&cmsgs[0])
1105+
if err != nil {
1106+
t.Fatal(err)
1107+
}
1108+
if len(cfds) != 1 {
1109+
t.Fatalf("got %d fds, want 1", len(cfds))
1110+
}
1111+
defer unix.Close(cfds[0])
1112+
}
1113+
10181114
// mktmpfifo creates a temporary FIFO and provides a cleanup function.
10191115
func mktmpfifo(t *testing.T) (*os.File, func()) {
10201116
err := unix.Mkfifo("fifo", 0666)

0 commit comments

Comments
 (0)