@@ -1015,6 +1015,102 @@ func TestSendmsgBuffers(t *testing.T) {
1015
1015
}
1016
1016
}
1017
1017
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
+
1018
1114
// mktmpfifo creates a temporary FIFO and provides a cleanup function.
1019
1115
func mktmpfifo (t * testing.T ) (* os.File , func ()) {
1020
1116
err := unix .Mkfifo ("fifo" , 0666 )
0 commit comments