3 ms·
I wrote the equivalent code in Go to see what happened https://play.golang.org/p/E3glBkbAo3 https://play.golang.org/p/E3glBkbAo3 (You'll need to run it locall
by nickcw 10y ago
I wrote the equivalent code in Go to see what happened
https://play.golang.org/p/E3glBkbAo3 https://play.golang.org/p/E3glBkbAo3
(You'll need to run it locally for the full effect - things on play are limited to a single thread.)
It didn't crash.
I wasn't suprised though as Go doesn't use the C library and its authors are very careful about multithreaded code.
- bonzini 10y agoIndeed go protects environment variable access with a lock. https://golang.org/src/syscall/env_unix.go https://golang.org/src/syscall/env_unix.go
- mzs 10y agomore importantly go never calls getenv()
- bonzini 10y agoNot "more importantly". It would have exactly the same behavior if it called getenv (and copied the result) under a mutex. And likewise it would be subject to use-after-free races if it didn't call getenv but also didn't use a mutex to protect its accesses. So the important bit is the mutex.
- mzs 10y agohttps://blog.golang.org/c-go-cgo https://blog.golang.org/c-go-cgo Say you call foo() in foo.c and foo() calls getenv() and setenv() with your mutex in the safeenv.go approach you described, all those calls from foo.c don't have the mutex around them that your foo.go uses. Worse yet it might not be your foo.c but part of libfoo in your OS.
- bonzini 10y agoBut Go's Setenv calls setenv_c, so a rogue C getenv would still be able to provoke races in Go code. Yes, a rogue C setenv would not provoke races in Go code calling getenv, but C interoperability is busted anyway---that's why I said that the mutex is the important part. It would work just as well (excluding cgo) if Go getenv called C getenv. They don't use getenv because it does a slow linear search, while Go can use a more efficient string->string map.