On Tuesday, April 28, 2020 at 12:05:00 AM UTC-7, Liam wrote:
>
>
>
> On Monday, April 27, 2020 at 10:00:52 PM UTC-7, Ian Lance Taylor wrote:
>>
>> On Mon, Apr 27, 2020 at 6:59 PM Liam <[email protected]> wrote:
>> >
>> > On Monday, April 27, 2020 at 5:56:52 PM UTC-7, Ian Lance Taylor wrote:
>> >>
>> >> On Mon, Apr 27, 2020 at 5:10 PM Liam <[email protected]> wrote:
>> >> >
>> >> > On Monday, April 27, 2020 at 4:22:41 PM UTC-7, Ian Lance Taylor
>> wrote:
>> >> >>
>> >> >> On Sun, Apr 26, 2020 at 4:55 PM Liam <[email protected]> wrote:
>> >> >> >
>> >> >> > During an io.Copy() where the Writer is a TCPConn and the Reader
>> is a 200K disk file, my code may concurrently Write() on the same TCPConn.
>> >> >> >
>> >> >> > I see the result of the Write() inserted into the result of the
>> io.Copy(). I had the impression that was impossible, but I must be
>> mistaken, as the sendfile(2) docs read:
>> >> >> >
>> >> >> > Note that a successful call to sendfile() may write fewer bytes
>> than requested; the caller should be prepared to retry the call if there
>> were unsent bytes.
>> >> >> >
>> >> >> > Could someone confirm that one must indeed synchronize concurrent
>> use of tcpConn.Write() and io.Copy(tcpConn, file)?
>> >> >>
>> >> >> Synchronization should not be required. internal/poll.Sendfile
>> >> >> acquires a write lock on dstFD, which is the TCP socket. That
>> should
>> >> >> ensure that the contents of an ordinary Write (which also acquires
>> a
>> >> >> write lock) should not interleave with the sendfile data.
>> >> >>
>> >> >> That said, if the sendfile system call cannot be used for whatever
>> >> >> reason, the net package will fall back on doing ordinary Read and
>> >> >> Write calls. And those Write calls can be interleaved with other
>> >> >> Write calls done by a different goroutine. I think that is
>> probably
>> >> >> permitted, in that io.Copy doesn't promise to not interleave with
>> >> >> simultaneous Write calls on the destination.
>> >> >>
>> >> >> So in the general case you should indeed use your own locking to
>> avoid
>> >> >> interleaving between io.Copy and a concurrent Write.
>> >> >
>> >> >
>> >> > Thanks for the details. Where could I add a Println() to reveal why
>> it doesn't call poll.Sendfile()?
>> >> >
>> >> > I expect this system to use sendfile(2). The file is a normal file
>> on a local partition (running on a Digital Ocean Droplet).
>> >> >
>> >> >
>> >> > /etc/fstab has:
>> >> > UUID=[omitted] / ext4 defaults 1 1
>> >> >
>> >> >
>> >> > $ df -h
>> >> > Filesystem Size Used Avail Use% Mounted on
>> >> > devtmpfs 981M 0 981M 0% /dev
>> >> > tmpfs 996M 0 996M 0% /dev/shm
>> >> > tmpfs 996M 436K 995M 1% /run
>> >> > tmpfs 996M 0 996M 0% /sys/fs/cgroup
>> >> > /dev/vda1 59G 5.7G 51G 11% /
>> >> > tmpfs 200M 0 200M 0% /run/user/0
>>
>
> Well this is a surprise... Added some println()s
>
> // my network setup
> aCfgTcp := net.ListenConfig{KeepAlive: -1}
> aListener, err := aCfgTcp.Listen(nil, iConf.Listen.Net,
> iConf.Listen.Laddr)
> if err != nil { return err }
> aCert, err := tls.LoadX509KeyPair(iConf.Listen.CertPath,
> iConf.Listen.KeyPath)
> if err != nil { return err }
> aCfgTls := tls.Config{Certificates: []tls.Certificate{aCert}}
> aListener = tls.NewListener(aListener, &aCfgTls)
>
I left out my accept loop:
var aConn net.Conn
for {
aConn, err = aListener.Accept()
...
Is this the root cause, as net.Listener only provides Accept() (Conn,
error), and net.Conn doesn't provide ReadFrom()?
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/2e4aba99-fa0a-4898-94f2-5af8c57e39af%40googlegroups.com.