| 21 | } |
| 22 | |
| 23 | func newParent(env *env) (*parent, map[fileName]*file, error) { |
| 24 | if env.getenv(sentinelEnvVar) == "" { |
| 25 | return nil, make(map[fileName]*file), nil |
| 26 | } |
| 27 | |
| 28 | wr := env.newFile(3, "write") |
| 29 | rd := env.newFile(4, "read") |
| 30 | |
| 31 | var names [][]string |
| 32 | dec := gob.NewDecoder(rd) |
| 33 | if err := dec.Decode(&names); err != nil { |
| 34 | return nil, nil, fmt.Errorf("can't decode names from parent process: %s", err) |
| 35 | } |
| 36 | |
| 37 | files := make(map[fileName]*file) |
| 38 | for i, parts := range names { |
| 39 | var key fileName |
| 40 | copy(key[:], parts) |
| 41 | |
| 42 | // Start at 5 to account for stdin, etc. and write |
| 43 | // and read pipes. |
| 44 | fd := 5 + i |
| 45 | env.closeOnExec(fd) |
| 46 | files[key] = &file{ |
| 47 | env.newFile(uintptr(fd), key.String()), |
| 48 | uintptr(fd), |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | result := make(chan error, 1) |
| 53 | exited := make(chan struct{}) |
| 54 | go func() { |
| 55 | defer rd.Close() |
| 56 | |
| 57 | n, err := io.Copy(ioutil.Discard, rd) |
| 58 | if n != 0 { |
| 59 | err = errors.New("unexpected data from parent process") |
| 60 | } else if err != nil { |
| 61 | err = fmt.Errorf("unexpected error while waiting for parent to exit: %s", err) |
| 62 | } |
| 63 | result <- err |
| 64 | close(exited) |
| 65 | }() |
| 66 | |
| 67 | return &parent{ |
| 68 | wr: wr, |
| 69 | result: result, |
| 70 | exited: exited, |
| 71 | }, files, nil |
| 72 | } |
| 73 | |
| 74 | func (ps *parent) sendReady() error { |
| 75 | defer ps.wr.Close() |