| 58 | } |
| 59 | |
| 60 | func startContainer(ctx context.Context, masterSocket int, containerPid int, e *engine.Engine, fatalChan chan error) { |
| 61 | comm := os.NewFile(uintptr(masterSocket), "master-socket") |
| 62 | if comm == nil { |
| 63 | fatalChan <- fmt.Errorf("bad master socket file descriptor") |
| 64 | return |
| 65 | } |
| 66 | conn, err := net.FileConn(comm) |
| 67 | comm.Close() |
| 68 | if err != nil { |
| 69 | fatalChan <- fmt.Errorf("failed to create master connection: %s", err) |
| 70 | return |
| 71 | } |
| 72 | defer conn.Close() |
| 73 | |
| 74 | data := make([]byte, 1) |
| 75 | |
| 76 | // special path for engines which needs to stop before executing |
| 77 | // container process |
| 78 | if obj, ok := e.Operations.(interface { |
| 79 | PreStartProcess(context.Context, int, net.Conn, chan error) error |
| 80 | }); ok { |
| 81 | _, err := conn.Read(data) |
| 82 | if err != nil { |
| 83 | if err != io.EOF { |
| 84 | fatalChan <- fmt.Errorf("error while reading master socket data: %s", err) |
| 85 | return |
| 86 | } |
| 87 | // EOF means something goes wrong in stage 2, don't send error via |
| 88 | // fatalChan, error will be reported by stage 2 and the process |
| 89 | // status will be set accordingly via MonitorContainer method below |
| 90 | sylog.Debugf("stage 2 process was interrupted, waiting status") |
| 91 | return |
| 92 | } else if data[0] == 'f' { |
| 93 | // StartProcess reported an error in stage 2, don't send error via |
| 94 | // fatalChan, error will be reported by stage 2 and the process |
| 95 | // status will be set accordingly via MonitorContainer method below |
| 96 | sylog.Debugf("stage 2 process reported an error, waiting status") |
| 97 | return |
| 98 | } |
| 99 | if err := obj.PreStartProcess(ctx, containerPid, conn, fatalChan); err != nil { |
| 100 | fatalChan <- fmt.Errorf("pre start process failed: %s", err) |
| 101 | return |
| 102 | } |
| 103 | } |
| 104 | // wait container process execution, EOF means container process |
| 105 | // was executed and master socket was closed by stage 2. If data |
| 106 | // byte sent is equal to 'f', it means an error occurred in |
| 107 | // StartProcess, just return by waiting error and process status |
| 108 | _, err = conn.Read(data) |
| 109 | if (err != nil && err != io.EOF) || data[0] == 'f' { |
| 110 | sylog.Debugf("stage 2 process reported an error, waiting status") |
| 111 | return |
| 112 | } |
| 113 | |
| 114 | err = e.PostStartProcess(ctx, containerPid) |
| 115 | if err != nil { |
| 116 | fatalChan <- fmt.Errorf("post start process failed: %s", err) |
| 117 | return |