Commit 4aa5dcc2 authored by Alex Brainman's avatar Alex Brainman

internal/poll: do not use Windows TransmitFile with pipes

It appears that TransmitFile Windows API does not work with Windows
pipes. So just copy data from pipe and into TCP connection manually.

Fixes #22278

Change-Id: I4810caca5345eac5bffb3176956689b8ae993256
Reviewed-on: https://go-review.googlesource.com/79775
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 7da2f827
...@@ -8,6 +8,15 @@ import "syscall" ...@@ -8,6 +8,15 @@ import "syscall"
// SendFile wraps the TransmitFile call. // SendFile wraps the TransmitFile call.
func SendFile(fd *FD, src syscall.Handle, n int64) (int64, error) { func SendFile(fd *FD, src syscall.Handle, n int64) (int64, error) {
ft, err := syscall.GetFileType(src)
if err != nil {
return 0, err
}
// TransmitFile does not work with pipes
if ft == syscall.FILE_TYPE_PIPE {
return 0, syscall.ESPIPE
}
if err := fd.writeLock(); err != nil { if err := fd.writeLock(); err != nil {
return 0, err return 0, err
} }
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"internal/testenv" "internal/testenv"
"io" "io"
"os"
"reflect" "reflect"
"runtime" "runtime"
"sync" "sync"
...@@ -722,3 +723,74 @@ func TestTCPBig(t *testing.T) { ...@@ -722,3 +723,74 @@ func TestTCPBig(t *testing.T) {
}) })
} }
} }
func TestCopyPipeIntoTCP(t *testing.T) {
ln, err := newLocalListener("tcp")
if err != nil {
t.Fatal(err)
}
defer ln.Close()
errc := make(chan error, 1)
defer func() {
if err := <-errc; err != nil {
t.Error(err)
}
}()
go func() {
c, err := ln.Accept()
if err != nil {
errc <- err
return
}
defer c.Close()
buf := make([]byte, 100)
n, err := io.ReadFull(c, buf)
if err != io.ErrUnexpectedEOF || n != 2 {
errc <- fmt.Errorf("got err=%q n=%v; want err=%q n=2", err, n, io.ErrUnexpectedEOF)
return
}
errc <- nil
}()
c, err := Dial("tcp", ln.Addr().String())
if err != nil {
t.Fatal(err)
}
defer c.Close()
r, w, err := os.Pipe()
if err != nil {
t.Fatal(err)
}
defer r.Close()
errc2 := make(chan error, 1)
defer func() {
if err := <-errc2; err != nil {
t.Error(err)
}
}()
defer w.Close()
go func() {
_, err := io.Copy(c, r)
errc2 <- err
}()
// Split write into 2 packets. That makes Windows TransmitFile
// drop second packet.
packet := make([]byte, 1)
_, err = w.Write(packet)
if err != nil {
t.Fatal(err)
}
time.Sleep(100 * time.Millisecond)
_, err = w.Write(packet)
if err != nil {
t.Fatal(err)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment