7fc93ec093
We could have gotten the signal before the handler was ready, which caused the process to wait indefinitely. This was the reason test.bash sometimes hung.
54 lines
1.2 KiB
Go
54 lines
1.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"github.com/rfjakob/gocryptfs/internal/tlog"
|
|
)
|
|
|
|
// The child sends us USR1 if the mount was successful. Exit with error code
|
|
// 0 if we get it.
|
|
func exitOnUsr1() {
|
|
c := make(chan os.Signal, 1)
|
|
signal.Notify(c, syscall.SIGUSR1)
|
|
go func() {
|
|
<-c
|
|
os.Exit(0)
|
|
}()
|
|
}
|
|
|
|
// forkChild - execute ourselves once again, this time with the "-fg" flag, and
|
|
// wait for SIGUSR1 or child exit.
|
|
// This is a workaround for the missing true fork function in Go.
|
|
func forkChild() int {
|
|
name := os.Args[0]
|
|
newArgs := []string{"-fg", fmt.Sprintf("-notifypid=%d", os.Getpid())}
|
|
newArgs = append(newArgs, os.Args[1:]...)
|
|
c := exec.Command(name, newArgs...)
|
|
c.Stdout = os.Stdout
|
|
c.Stderr = os.Stderr
|
|
c.Stdin = os.Stdin
|
|
exitOnUsr1()
|
|
err := c.Start()
|
|
if err != nil {
|
|
tlog.Fatal.Printf("forkChild: starting %s failed: %v\n", name, err)
|
|
return 1
|
|
}
|
|
err = c.Wait()
|
|
if err != nil {
|
|
if exiterr, ok := err.(*exec.ExitError); ok {
|
|
if waitstat, ok := exiterr.Sys().(syscall.WaitStatus); ok {
|
|
os.Exit(waitstat.ExitStatus())
|
|
}
|
|
}
|
|
tlog.Fatal.Printf("forkChild: wait returned an unknown error: %v\n", err)
|
|
return 1
|
|
}
|
|
// The child exited with 0 - let's do the same.
|
|
return 0
|
|
}
|