Created
April 9, 2021 17:13
-
-
Save poolpOrg/6ddd5226f59ef60f4af1ade97aed8566 to your computer and use it in GitHub Desktop.
ipcmsg example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"log" | |
"os" | |
"os/exec" | |
"syscall" | |
"time" | |
"github.com/poolpOrg/ipcmsg" | |
) | |
// fork a child and build an ipcmsg channel over the child fd | |
// | |
func parent() { | |
log.Println("starting parent") | |
pid, fd := fork_child() | |
_, child_w := ipcmsg.Channel(pid, fd) | |
for { | |
time.Sleep(1 * time.Second) | |
pfd, _ := syscall.Open("/private/etc/passwd", 0700, 0) | |
child_w <- ipcmsg.MessageWithFd(42, []byte("foobar"), pfd) | |
child_w <- ipcmsg.Message(42, []byte("barbaz")) | |
child_w <- ipcmsg.Message(42, []byte("barbaz")) | |
child_w <- ipcmsg.Message(42, []byte("barbaz")) | |
child_w <- ipcmsg.Message(42, []byte("barbaz")) | |
} | |
} | |
// build an ipcmsg channel over fd 3 | |
// | |
func child() { | |
log.Println("hellow, i'm child of", os.Getppid()) | |
parent_r, _ := ipcmsg.Channel(os.Getppid(), 3) | |
for { | |
msg := <-parent_r | |
if msg.Fd != -1 { | |
log.Println(string(msg.Data), "fd=", msg.Fd) | |
syscall.Close(msg.Fd) | |
} else { | |
log.Println(string(msg.Data), "nofd") | |
} | |
} | |
} | |
// fork a child and reexec the process with env REEXEC=CHILD so executable can assign a | |
// different task to child in main() | |
// | |
func fork_child() (int, int) { | |
binary, err := exec.LookPath(os.Args[0]) | |
if err != nil { | |
log.Fatal(err) | |
} | |
sp, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, syscall.AF_UNSPEC) | |
if err != nil { | |
log.Fatal(err) | |
} | |
procAttr := syscall.ProcAttr{} | |
procAttr.Files = []uintptr{ | |
uintptr(syscall.Stdin), | |
uintptr(syscall.Stdout), | |
uintptr(syscall.Stderr), | |
uintptr(sp[0]), | |
} | |
procAttr.Env = []string{ | |
"REEXEC=CHILD", | |
} | |
var pid int | |
pid, err = syscall.ForkExec(binary, []string{os.Args[0]}, &procAttr) | |
if err != nil { | |
log.Fatal(err) | |
} | |
if syscall.Close(sp[0]) != nil { | |
log.Fatal(err) | |
} | |
return pid, sp[1] | |
} | |
// execute parent() or child() depending on the process REEXEC name | |
// | |
func main() { | |
reexec := os.Getenv("REEXEC") | |
switch reexec { | |
case "": | |
parent() | |
case "CHILD": | |
child() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment