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

os: Getpid() returns parent's PID even called from sub process #59370

Closed
keakon opened this issue Apr 1, 2023 · 2 comments
Closed

os: Getpid() returns parent's PID even called from sub process #59370

keakon opened this issue Apr 1, 2023 · 2 comments

Comments

@keakon
Copy link

keakon commented Apr 1, 2023

What version of Go are you using (go version)?

$ go version
go version go1.20.2 darwin/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/keakon/Library/Caches/go-build"
GOENV="/Users/keakon/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/keakon/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/keakon/go"
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"
GOROOT="/usr/local/Cellar/go/1.20.2/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.20.2/libexec/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.20.2"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="cc"
CXX="c++"
CGO_ENABLED="1"
GOMOD="/dev/null"
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 -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/jw/d0g3224x6tx5dwqrvkl8pp440000gn/T/go-build1704497747=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

Run this code:

package main

import (
	"fmt"
	"os"
	"syscall"
)

func main() {
	r1, r2, err := syscall.Syscall(syscall.SYS_FORK, 0, 0, 0)
	if err != 0 {
		panic(err)
	}
	fmt.Println("Pid of sub process is", r1)
	if r2 == 0 { // parent
		fmt.Println("os.Getpid() of parent process is", os.Getpid())
	} else { // sub
		fmt.Println("os.Getpid() of sub process is", os.Getpid())
	}
}

What did you expect to see?

Pid of sub process is 8048
os.Getpid() of parent process is 8047
Pid of sub process is 8048
os.Getpid() of sub process is 8048

What did you see instead?

Pid of sub process is 8048
os.Getpid() of parent process is 8047
Pid of sub process is 8048
os.Getpid() of sub process is 8047

@rittneje
Copy link

rittneje commented Apr 1, 2023

It looks like on macos, Go hooks into libc's getpid implementation. I am seeing some references to libc attempting to cache the result instead of making the syscall each time, but I cannot find anything authoritative for macos. My guess is since you are directly issuing the SYS_FORK syscall, this cache is not being invalidated, hence os.Getpid returns the wrong thing. Note that if you directly do syscall.Syscall(syscall.SYS_GETPID, 0, 0, 0) it gives the right answer.

@odeke-em odeke-em changed the title affected/package: os.Getpid() returns parent's pid even called from sub process os: Getpid() returns parent's PID even called from sub process Apr 2, 2023
@bcmills
Copy link
Contributor

bcmills commented Apr 3, 2023

When it comes to SYS_FORK, if you break it, you get to keep all the pieces. Use syscall.ForkExec or (better still) os/exec instead.

(https://www.microsoft.com/en-us/research/publication/a-fork-in-the-road/ is a good read; search in particular for “Fork isn't thread-safe.”)

@bcmills bcmills closed this as not planned Won't fix, can't repro, duplicate, stale Apr 3, 2023
@golang golang locked and limited conversation to collaborators Apr 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants