Closed
Description
Go version
go version go1.19
Output of go env
in your module/workspace:
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/acmcoder/.cache/go-build"
GOENV="/home/acmcoder/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/acmcoder/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/acmcoder/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="off"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.19.13"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build6687487=/tmp/go-build -gno-record-gcc-switches"
What did you do?
When we use unix.Prlimit
to set other process's nofile limit, we should not clear the calling process's nofile limit cache, it will cause the nofile limit setting invalid when we use unix.Exec
.
The reprodecing code:
package main
import (
"fmt"
"os"
"os/exec"
"golang.org/x/sys/unix"
)
func main() {
// Usage: ./prlimit true or ./prlimit false
ifPrlimit := os.Args[1]
if ifPrlimit == "true" {
fmt.Println("Prlimit is true")
} else {
fmt.Println("Prlimit is false")
}
// Start a child process firstly,
// so we can use Prlimit to set it's nofile rlimit.
cmd := exec.Command("sleep", "infinity")
cmd.Start()
// To print out the process's nofile limit
var lim unix.Rlimit
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &lim); err == nil {
fmt.Printf("(1) init curr: %d, max: %d\n", lim.Cur, lim.Max)
}
// If we run ./prlimit true, we use unix.Prlimit to set child process's nofile limit,
// then it will cause a bug for calling process.
if ifPrlimit == "true" {
if err := unix.Prlimit(cmd.Process.Pid, unix.RLIMIT_NOFILE, &lim, nil); err != nil {
fmt.Println("Prlimit failed", err)
}
cmd.Process.Kill()
cmd.Process.Wait()
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &lim); err == nil {
fmt.Printf("(2) after Prlimit other process, curr: %d, max: %d\n", lim.Cur, lim.Max)
}
}
// The above mentiond bug is here.
unix.Exec("/bin/sh", []string{"/bin/sh", "-c", "ulimit -n"}, os.Environ())
}
What did you see happen?
acmcoder@acmcoder:~/rlimits$ # Execve a process without Prlimit
acmcoder@acmcoder:~/rlimits$ ./prlimit false
Prlimit is false
(1) init curr: 1048576, max: 1048576
1024
acmcoder@acmcoder:~/rlimits$ # Execve a process after Prlimit
acmcoder@acmcoder:~/rlimits$ ./prlimit true
Prlimit is true
(1) init curr: 1048576, max: 1048576
(2) after Prlimit other process, curr: 1048576, max: 1048576
1048576
What did you expect to see?
The last output of ./prlimit true
should be the same as ./prlimit false
.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Done