In my open source file descriptor leak checker (Linux only) for Gomega, 
Go's race detector flags a race condition in my code where I need to check 
whether a Cmd.Process already has terminated 
<https://github.com/thediveo/fdooze/blob/05aae68770fd287e51aea8dd55ff336164cb3f49/session/session_fds.go#L21>
 
as its ProcessState has been set.

if session.Command.ProcessState != nil {
    return nil, errors.New("session has already ended")
}

Now, this check might be called be called from a different Goroutine than 
another Goroutine waiting for the command to exit. In particular, this is 
the (what I consider to be the relevant) output of the race detector:

WARNING: DATA RACE
Write at 0x00c0002e8208 by goroutine 16:
  os/exec.(*Cmd).Wait()
      /home/.../sdk/go1.19rc2/src/os/exec/exec.go:598 +0x1eb
  github.com/onsi/gomega/gexec.(*Session).monitorForExit()
      
/home/.../go/pkg/mod/github.com/onsi/gomega@v1.20.0/gexec/session.go:197 
+0x44
  github.com/onsi/gomega/gexec.Start.func1()
      
/home/.../go/pkg/mod/github.com/onsi/gomega@v1.20.0/gexec/session.go:96 
+0x47

Previous read at 0x00c0002e8208 by goroutine 12:
  github.com/thediveo/fdooze/session.FiledescriptorsFor()
      /home/.../github/fdooze/session/session_fds.go:21 +0x1b7
  github.com/thediveo/fdooze/session.glob..func1.1.1()
      /home/.../github/fdooze/session/session_fds_test.go:45 +0x30
  runtime.call16()
      /home/.../sdk/go1.19rc2/src/runtime/asm_amd64.s:724 +0x48
  reflect.Value.Call()
      /home/.../sdk/go1.19rc2/src/reflect/value.go:368 +0xc7
  github.com/onsi/gomega/internal.NewAsyncAssertion.func1()
      
/home/.../go/pkg/mod/github.com/onsi/gomega@v1.20.0/internal/async_assertion.go:48
 
+0x16e
  github.com/onsi/gomega/internal.(*AsyncAssertion).pollActual()
      
/home/.../go/pkg/mod/github.com/onsi/gomega@v1.20.0/internal/async_assertion.go:132
 
+0x82
  github.com/onsi/gomega/internal.(*AsyncAssertion).match()
      
/home/.../go/pkg/mod/github.com/onsi/gomega@v1.20.0/internal/async_assertion.go:162
 
+0xe4
  github.com/onsi/gomega/internal.(*AsyncAssertion).ShouldNot()
      
/home/.../go/pkg/mod/github.com/onsi/gomega@v1.20.0/internal/async_assertion.go:112
 
+0xa9
  github.com/thediveo/fdooze/session.glob..func1.1()
      /home/.../github/fdooze/session/session_fds_test.go:65 +0xf41
  github.com/onsi/ginkgo/v2/internal.(*Suite).runNode.func2()
      
/home/.../go/pkg/mod/github.com/onsi/ginkgo/v2@v2.1.4/internal/suite.go:596 
+0xea

Is there actually any way to check use Cmd.ProcessState at all from a 
thread different from the one doing a Cmd.Wait? Might this be a design 
"weakness" of the Cmd type in that it doesn't cover such use cases?

Any idea for a work around to find if the command might already have 
(prematurely) finished by the time I try to check for its open file 
descriptors?

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/8ed84076-b29d-4840-8c15-09621e2fca61n%40googlegroups.com.

Reply via email to