Skip to content

Commit 96e75de

Browse files
dpifkegopherbot
authored andcommitted
unix: improve Sendmsg and Recvmsg documentation
This clarifies these functions' behavior when the non-control data is empty but there is a control data present. It also makes clear the difference between Sendmsg, SendmsgN, and SendmsgBuffers, and between Recvmsg and RecvmsgBuffers. Fixes golang/go#56911 Change-Id: I1e35659e66e493c192af7f5a426a316f6052475c Reviewed-on: https://go-review.googlesource.com/c/sys/+/456816 Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: Than McIntosh <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]>
1 parent 127c0dd commit 96e75de

File tree

1 file changed

+45
-10
lines changed

1 file changed

+45
-10
lines changed

unix/syscall_unix.go

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,19 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
331331
return
332332
}
333333

334+
// Recvmsg receives a message from a socket using the recvmsg system call. The
335+
// received non-control data will be written to p, and any "out of band"
336+
// control data will be written to oob. The flags are passed to recvmsg.
337+
//
338+
// The results are:
339+
// - n is the number of non-control data bytes read into p
340+
// - oobn is the number of control data bytes read into oob; this may be interpreted using [ParseSocketControlMessage]
341+
// - recvflags is flags returned by recvmsg
342+
// - from is the address of the sender
343+
//
344+
// If the underlying socket type is not SOCK_DGRAM, a received message
345+
// containing oob data and a single '\0' of non-control data is treated as if
346+
// the message contained only control data, i.e. n will be zero on return.
334347
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
335348
var iov [1]Iovec
336349
if len(p) > 0 {
@@ -346,13 +359,9 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
346359
return
347360
}
348361

349-
// RecvmsgBuffers receives a message from a socket using the recvmsg
350-
// system call. The flags are passed to recvmsg. Any non-control data
351-
// read is scattered into the buffers slices. The results are:
352-
// - n is the number of non-control data read into bufs
353-
// - oobn is the number of control data read into oob; this may be interpreted using [ParseSocketControlMessage]
354-
// - recvflags is flags returned by recvmsg
355-
// - from is the address of the sender
362+
// RecvmsgBuffers receives a message from a socket using the recvmsg system
363+
// call. This function is equivalent to Recvmsg, but non-control data read is
364+
// scattered into the buffers slices.
356365
func RecvmsgBuffers(fd int, buffers [][]byte, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
357366
iov := make([]Iovec, len(buffers))
358367
for i := range buffers {
@@ -371,11 +380,38 @@ func RecvmsgBuffers(fd int, buffers [][]byte, oob []byte, flags int) (n, oobn in
371380
return
372381
}
373382

383+
// Sendmsg sends a message on a socket to an address using the sendmsg system
384+
// call. This function is equivalent to SendmsgN, but does not return the
385+
// number of bytes actually sent.
374386
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
375387
_, err = SendmsgN(fd, p, oob, to, flags)
376388
return
377389
}
378390

391+
// SendmsgN sends a message on a socket to an address using the sendmsg system
392+
// call. p contains the non-control data to send, and oob contains the "out of
393+
// band" control data. The flags are passed to sendmsg. The number of
394+
// non-control bytes actually written to the socket is returned.
395+
//
396+
// Some socket types do not support sending control data without accompanying
397+
// non-control data. If p is empty, and oob contains control data, and the
398+
// underlying socket type is not SOCK_DGRAM, p will be treated as containing a
399+
// single '\0' and the return value will indicate zero bytes sent.
400+
//
401+
// The Go function Recvmsg, if called with an empty p and a non-empty oob,
402+
// will read and ignore this additional '\0'. If the message is received by
403+
// code that does not use Recvmsg, or that does not use Go at all, that code
404+
// will need to be written to expect and ignore the additional '\0'.
405+
//
406+
// If you need to send non-empty oob with p actually empty, and if the
407+
// underlying socket type supports it, you can do so via a raw system call as
408+
// follows:
409+
//
410+
// msg := &unix.Msghdr{
411+
// Control: &oob[0],
412+
// }
413+
// msg.SetControllen(len(oob))
414+
// n, _, errno := unix.Syscall(unix.SYS_SENDMSG, uintptr(fd), uintptr(unsafe.Pointer(msg)), flags)
379415
func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
380416
var iov [1]Iovec
381417
if len(p) > 0 {
@@ -394,9 +430,8 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
394430
}
395431

396432
// SendmsgBuffers sends a message on a socket to an address using the sendmsg
397-
// system call. The flags are passed to sendmsg. Any non-control data written
398-
// is gathered from buffers. The function returns the number of bytes written
399-
// to the socket.
433+
// system call. This function is equivalent to SendmsgN, but the non-control
434+
// data is gathered from buffers.
400435
func SendmsgBuffers(fd int, buffers [][]byte, oob []byte, to Sockaddr, flags int) (n int, err error) {
401436
iov := make([]Iovec, len(buffers))
402437
for i := range buffers {

0 commit comments

Comments
 (0)