FreeBSD Bugzilla – Attachment 254879 Details for
Bug 282495
Linuxulator sendfile returns EAGAIN repeatedly, actually repeatingly sending (the same) data
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
Simple Go executable that shows an adapted internal Go sendfile wrapper exercising the apparent bug
main.go (text/plain), 2.54 KB, created by
pieter
on 2024-11-02 16:27:07 UTC
(
hide
)
Description:
Simple Go executable that shows an adapted internal Go sendfile wrapper exercising the apparent bug
Filename:
MIME Type:
Creator:
pieter
Created:
2024-11-02 16:27:07 UTC
Size:
2.54 KB
patch
obsolete
>package main > >import ( > "net" > "os" > "syscall" > "fmt" > //"io" >) > >func CheckError(err error) { > if err != nil { > fmt.Fprintf(os.Stderr, "Fatal error: %s\n", err.Error()) > os.Exit(1) > } >} > >const maxSendfileSize int = 4 << 20 >func SendFile(dst int, src int, remain int64) (written int64, err error, handled bool) { > for remain > 0 { > fmt.Printf("Entering loop, remain = %d\n", remain) > n := maxSendfileSize > if int64(n) > remain { > n = int(remain) > } > n, err = syscall.Sendfile(dst, src, nil, n) > fmt.Printf("syscall returned n=%d, err=%s\n", n, err) > > if n > 0 { > written += int64(n) > remain -= int64(n) > fmt.Printf("Sendfile syscall success, written: %d, remain: %d\n", written, remain) > continue > } else if err != syscall.EAGAIN && err != syscall.EINTR { > // This includes syscall.ENOSYS (no kernel > // support) and syscall.EINVAL (fd types which > // don't implement sendfile), and other errors. > // We should end the loop when there is no error > // returned from sendfile(2) or it is not a retryable error. > fmt.Printf("Error, but not EAGAIN nor EINTR, breaking out of the loop\n") > break > } > if err == syscall.EINTR { > fmt.Printf("Error EINTR, looping back\n") > continue > } > if err == syscall.EAGAIN { > fmt.Printf("Error EAGAIN, stopping to see if anything was sent\n") > break > } >/* > // In my rewrite there's no dstFD and couldn't directly find what this does. But it doesn't seem > // to matter for reproducing the issue. > if err = dstFD.pd.waitWrite(dstFD.isFile); err != nil { > break > } >*/ > } > handled = written != 0 || (err != syscall.ENOSYS && err != syscall.EINVAL) > return >} > >func main() { > srcFile := "./file2" > serverAddr := "localhost:4040" > > // server start listenning > server, err := net.Listen("tcp", serverAddr) > CheckError(err) > defer server.Close() > > for true { > sendFile(server, srcFile) > } >} > > >func sendFile(server net.Listener, srcFile string) { > // accept connection > conn, err := server.Accept() > CheckError(err) > > // open file to send > fi, err := os.Open(srcFile) > CheckError(err) > defer fi.Close() > > fs, err := fi.Stat() > CheckError(err) > n := fs.Size() > > src := int(fi.Fd()) > dstF, _ := conn.(*net.TCPConn).File() > CheckError(err) > dst := int(dstF.Fd()) > > > // set non-blocking > syscall.SetNonblock(dst, true); > > // send file to client > //n, err = syscall.Sendfile(dst, src, nil, n) > //_, err = io.CopyN(conn, fi, n) > //n, err = conn.(*net.TCPConn).ReadFrom(fi) > > n, err, handled := SendFile(dst, src, n) > CheckError(err) > fmt.Fprintf(os.Stdout, "Wrote %d bytes, handled: %s", n, handled) > conn.(*net.TCPConn).Close() >} >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 282495
: 254879