(env *env, passedFiles map[fileName]*file)
| 16 | } |
| 17 | |
| 18 | func startChild(env *env, passedFiles map[fileName]*file) (*child, error) { |
| 19 | // These pipes are used for communication between parent and child |
| 20 | // readyW is passed to the child, readyR stays with the parent |
| 21 | readyR, readyW, err := os.Pipe() |
| 22 | if err != nil { |
| 23 | return nil, fmt.Errorf("pipe failed: %s", err) |
| 24 | } |
| 25 | |
| 26 | namesR, namesW, err := os.Pipe() |
| 27 | if err != nil { |
| 28 | readyR.Close() |
| 29 | readyW.Close() |
| 30 | return nil, fmt.Errorf("pipe failed: %s", err) |
| 31 | } |
| 32 | |
| 33 | // Copy passed fds and append the notification pipe |
| 34 | fds := []*os.File{os.Stdin, os.Stdout, os.Stderr, readyW, namesR} |
| 35 | var fdNames [][]string |
| 36 | for name, file := range passedFiles { |
| 37 | nameSlice := make([]string, len(name)) |
| 38 | copy(nameSlice, name[:]) |
| 39 | fdNames = append(fdNames, nameSlice) |
| 40 | fds = append(fds, file.File) |
| 41 | } |
| 42 | |
| 43 | // Copy environment and append the notification env vars |
| 44 | sentinel := fmt.Sprintf("%s=yes", sentinelEnvVar) |
| 45 | var environ []string |
| 46 | for _, val := range env.environ() { |
| 47 | if val != sentinel { |
| 48 | environ = append(environ, val) |
| 49 | } |
| 50 | } |
| 51 | environ = append(environ, sentinel) |
| 52 | |
| 53 | proc, err := env.newProc(os.Args[0], os.Args[1:], fds, environ) |
| 54 | if err != nil { |
| 55 | readyR.Close() |
| 56 | readyW.Close() |
| 57 | namesR.Close() |
| 58 | namesW.Close() |
| 59 | return nil, fmt.Errorf("can't start process %s: %s", os.Args[0], err) |
| 60 | } |
| 61 | |
| 62 | exited := make(chan struct{}) |
| 63 | result := make(chan error, 1) |
| 64 | ready := make(chan *os.File, 1) |
| 65 | |
| 66 | c := &child{ |
| 67 | env, |
| 68 | proc, |
| 69 | readyR, |
| 70 | namesW, |
| 71 | ready, |
| 72 | result, |
| 73 | exited, |
| 74 | } |
| 75 | go c.writeNames(fdNames) |
searching dependent graphs…