Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/link: cannot fallocate file in tmpfs on EulerOS when cpuprofile is on #69137

Closed
alexanius opened this issue Aug 29, 2024 · 5 comments
Closed
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Milestone

Comments

@alexanius
Copy link

Go version

go version devel go1.24-6edc1c23ed Thu Aug 22 01:18:23 2024 +0000 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/amarkin/.cache/go-build'
GOENV='/home/amarkin/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/amarkin/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/amarkin/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/amarkin/repo/go_bb'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/amarkin/repo/go_bb/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='devel go1.24-6edc1c23ed Thu Aug 22 01:18:23 2024 +0000'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/amarkin/.config/go/telemetry'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/home/amarkin/repo/benchmarks/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2988943068=/tmp/go-build -gno-record-gcc-switches'

What did you do?

$ cat t.go
package main

import (
        "os"
        "runtime/pprof"
        "syscall"
)

func main() {
        f, _ := os.Create("t.pprof")
        pprof.StartCPUProfile(f)

        ff, _ := os.Create("/tmp/ttt")
        for i := 0 ; ; i++ {
                if  err := syscall.Fallocate(int(ff.Fd()), 0, 0, 250000000); err != syscall.EINTR {
                        break
                }
                println("Fail:", i)
        }
        println("Success")

        pprof.StopCPUProfile()
        f.Close()
}

$ ~/repo/CoreGo/bin/go run t.go
Fail: 0
Fail: 1
Fail: 2
Fail: 3
Fail: 4
Fail: 5
Fail: 6
...

What did you see happen?

The program can not make Fallocate and goes into infinite loop.

What did you expect to see?

The program makes changes the file size.

Explanation

This situation happens when few factors are met in the same time:

  • EulerOs
  • The cpu profiling is turned on
  • We try to change size of the file on tmpfs

The real-world situation happened, when I tried to measure sweet benchmark in the pgo mode on my performance server. The problematic callstack is the following:

#0  syscall.Fallocate (fd=7, mode=0, off=0, len=241786748, err=...) at /home/amarkin/repo/go_bb/src/syscall/zsyscall_linux_amd64.go:387
#1  0x00000000005fe9da in cmd/link/internal/ld.(*OutBuf).fallocate (out=<optimized out>, size=<optimized out>, ~r0=...) at /home/amarkin/repo/go_bb/src/cmd/link/internal/ld/outbuf_linux.go:10
#2  0x00000000005fea8c in cmd/link/internal/ld.(*OutBuf).Mmap (out=0xc0000920e0, filesize=241786748, err=...) at /home/amarkin/repo/go_bb/src/cmd/link/internal/ld/outbuf_mmap.go:23
#3  0x00000000005fd075 in cmd/link/internal/ld.Main (arch=0x90e340, theArch=...) at /home/amarkin/repo/go_bb/src/cmd/link/internal/ld/main.go:444
#4  0x0000000000684cfb in main.main () at /home/amarkin/repo/go_bb/src/cmd/link/main.go:72

The problematic code is in the cmd/link/internal/ld.(*OutBuf).Mmap:

        for {
                if err = out.fallocate(filesize); err != syscall.EINTR {
                        break
                }
        }

The fallocate always returns EINTR and the code do not leave the loop. I found, that other people faced the similar problems, but their solution was the loop above.

My solution of this problem was to replace the fallocate with ftruncate syscall in the following way:

        for i := 0 ; ; i++ {
                if i < 100 {
                        if  err = out.fallocate(filesize); err != syscall.EINTR {
                                break
                        }
                } else {
                        if  err = out.ftruncate(filesize); err != syscall.EINTR {
                                break
                        }
                }
        }

That workaround worked, and I'd like to ask the advice what is the best way to solve the problem?

@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Aug 29, 2024
@ianlancetaylor ianlancetaylor changed the title syscall: Cannot fallocate file in tmpfs on EulerOs when cpuprofile is on cmd/link: cannot fallocate file in tmpfs on EulerOs when cpuprofile is on Aug 29, 2024
@ianlancetaylor ianlancetaylor changed the title cmd/link: cannot fallocate file in tmpfs on EulerOs when cpuprofile is on runtime: cannot fallocate file in tmpfs on EulerOs when cpuprofile is on Aug 29, 2024
@ianlancetaylor
Copy link
Contributor

Retrying on EINTR is the right fix.

@ianlancetaylor ianlancetaylor changed the title runtime: cannot fallocate file in tmpfs on EulerOs when cpuprofile is on cmd/link: cannot fallocate file in tmpfs on EulerOs when cpuprofile is on Aug 29, 2024
@ianlancetaylor
Copy link
Contributor

Hmmm, I see though, you are saying that the system call never succeeds. It always gets interrupted. That seems like it might be a kernel bug. I'm not familiar with EulerOS. Does this happen on other Linux distributions?

@alexanius
Copy link
Author

Hmmm, I see though, you are saying that the system call never succeeds. It always gets interrupted. That seems like it might be a kernel bug. I'm not familiar with EulerOS. Does this happen on other Linux distributions?

As I can see - some users faced this problem (see link ). The kernel has the patch for this situation, but it is quite recent. I'll try to communicate with Euler developers and ask what they think.

@dmitshur dmitshur added this to the Backlog milestone Sep 4, 2024
@dmitshur dmitshur added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Sep 4, 2024
@dmitshur dmitshur changed the title cmd/link: cannot fallocate file in tmpfs on EulerOs when cpuprofile is on cmd/link: cannot fallocate file in tmpfs on EulerOS when cpuprofile is on Sep 4, 2024
@cherrymui cherrymui added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Sep 4, 2024
@gopherbot
Copy link
Contributor

Timed out in state WaitingForInfo. Closing.

(I am just a bot, though. Please speak up if this is a mistake or you have the requested information.)

@gopherbot gopherbot closed this as not planned Won't fix, can't repro, duplicate, stale Oct 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
Development

No branches or pull requests

7 participants
@alexanius @dmitshur @ianlancetaylor @gopherbot @cherrymui @gabyhelp and others