Skip to content

Instantly share code, notes, and snippets.

@hayajo
Last active November 7, 2017 07:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hayajo/9cb78732590d5c67c149cd95711d0e51 to your computer and use it in GitHub Desktop.
Save hayajo/9cb78732590d5c67c149cd95711d0e51 to your computer and use it in GitHub Desktop.
CLONE_FILE と Cmd.ExtraFiles
package main
import (
"fmt"
"io/ioutil"
"os"
"syscall"
"time"
)
func init() {
if os.Args[0] == "child" {
time.Sleep(time.Second * 1)
r1 := os.NewFile(uintptr(254), "r1")
b1, err := ioutil.ReadAll(r1)
if err != nil {
panic(err)
}
r2 := os.NewFile(uintptr(253), "r2")
b2, err := ioutil.ReadAll(r2)
if err != nil {
panic(err) // "unshare"されるとこちらのfdは共有されないためpanicになる
}
fmt.Printf("data received from parent: %s %s\n", string(b1), string(b2))
os.Exit(0)
}
}
func main() {
r1, w1, err := os.Pipe()
if err != nil {
panic(err)
}
defer r1.Close()
syscall.Dup3(int(r1.Fd()), 254, 0)
if _, err := w1.Write([]byte("Hello")); err != nil {
panic(err)
}
w1.Close()
proc, err := os.StartProcess("/proc/self/exe", []string{"child"}, &os.ProcAttr{
Files: []*os.File{
nil,
os.Stdout,
os.Stderr,
},
Sys: &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_FILES,
},
})
if err != nil {
panic(err)
}
if len(os.Args) > 1 && os.Args[1] == "unshare" {
// 以後のfdは共有しない
if err := syscall.Unshare(syscall.CLONE_FILES); err != nil {
panic(err)
}
}
r2, w2, err := os.Pipe()
if err != nil {
panic(err)
}
defer r2.Close()
syscall.Dup3(int(r2.Fd()), 253, 0) // CLONE_FILESでfdを共有しているので子プロセスでもこちらを参照できる
if _, err := w2.Write([]byte("World")); err != nil {
panic(err)
}
w2.Close()
state, _ := proc.Wait()
fmt.Printf("child state: %v\n", state)
}
package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
)
func init() {
if os.Args[0] == "child" {
r := os.NewFile(uintptr(3), "r")
b, err := ioutil.ReadAll(r)
if err != nil {
panic(err)
}
fmt.Printf("data received from parent: %s\n", string(b))
os.Exit(0)
}
}
func main() {
r, w, err := os.Pipe()
if err != nil {
panic(err)
}
defer r.Close()
if _, err := w.Write([]byte("Hello World")); err != nil {
panic(err)
}
w.Close()
cmd := exec.Command("/proc/self/exe")
cmd.Args[0] = "child"
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.ExtraFiles = []*os.File{r} // fdは3+iとなる
if err := cmd.Start(); err != nil {
panic(err)
}
cmd.Wait()
}
@hayajo
Copy link
Author

hayajo commented Jul 15, 2017

CLONE_FILESはこちらを参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment