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

syscall: can't inherit fcntlFlock on linux after syscall.Exec #25249

Closed
sakeven opened this issue May 4, 2018 · 6 comments
Closed

syscall: can't inherit fcntlFlock on linux after syscall.Exec #25249

sakeven opened this issue May 4, 2018 · 6 comments

Comments

@sakeven
Copy link

@sakeven sakeven commented May 4, 2018

Please answer these questions before submitting your issue. Thanks!

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

go version go1.10.1 linux/amd64
go version go1.8.5 linux/amd64
go version go1.10.2 linux/amd64

Does this issue reproduce with the latest release?

Yes

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

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/chenlin/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build057651522=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

What did you do?

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

See code:
https://play.golang.org/p/jTMF5dejA74

What did you expect to see?

Should inherit fcntlFlock on linux after syscall.Exec.

man 2 fcntl:

Record locks are not inherited by a child created via fork(2), but are preserved across an execve(2).

I test c code below. It can inherit fcntlFlock on linux after exceve.

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main() {
    printf("begin %d\n", getpid());
    int fd = open("lock", O_WRONLY | O_CREAT | O_TRUNC , 0777);
    if (fd < 0 ) {
      printf("fail to open");
      return -1;
    }

    printf("fd %d\n", fd); 

    struct flock fl ;
    fl.l_type = F_WRLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = 0;
    fl.l_len = 0;
    
    int errno = fcntl(fd, F_SETLK, &fl);
    if( errno != 0) {
      printf("err %d", errno);
      return -1;
    }

    sleep(5);
    char *env[] = { NULL };
    char *argv[] = {"./test.sh", NULL};
    execve(argv[0], argv, env);
    return 0;
}

I also test go code on macOS. It can inherit fcntlFlock on macOS after syscall.Exec, too.

What did you see instead?

Can't inherit fcntlFlock on linux after syscall.Exec.

@sakeven sakeven changed the title can't inherit fcntlFlock on linux after syscall.Exec syscall: can't inherit fcntlFlock on linux after syscall.Exec May 4, 2018
@tklauser
Copy link
Member

@tklauser tklauser commented May 4, 2018

@bradfitz bradfitz added this to the Go1.12 milestone May 4, 2018
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented May 4, 2018

I expect that the key difference is that Go files are all opened with O_CLOEXEC. Try adding that to the flags you pass to open in your C program. If that is the problem as I expect, then you'll need to modify your Go program to import golang.org/x/sys/unix and use unix.FcntlInt(fd, F_SETFD, 0) to clear the FD_CLOEXEC flag.

@sakeven
Copy link
Author

@sakeven sakeven commented May 5, 2018

@ianlancetaylor I used syscall.Open rather than os.Open. I know os.Open will open files with O_CLOEXEC, but syscall.Open not.

Also I tryed clearing the FD_CLOEXEC flag after os.Open and it met the problem again.

@sakeven
Copy link
Author

@sakeven sakeven commented May 7, 2018

It seems that it's a problem with Linux kernel.
In a multi-threaded environment the fcntlFlock may be released when execve.

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented May 7, 2018

Thanks for following up. I'll close this issue since it sounds like there is nothing we can change in Go to fix it. Please comment if you disagree.

@gopherbot
Copy link

@gopherbot gopherbot commented May 23, 2018

Change https://golang.org/cl/114090 mentions this issue: compiler: fix DWARF inline debug issue with dead local vars

@golang golang locked and limited conversation to collaborators May 23, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can’t perform that action at this time.