Normally, this function does not return. If it returns, with or without an error, it means the initialization has failed. If the error is returned, it means the error can not be communicated back to the parent.
()
| 126 | // error, it means the initialization has failed. If the error is returned, |
| 127 | // it means the error can not be communicated back to the parent. |
| 128 | func startInitialization() (retErr error) { |
| 129 | // Get the synchronisation pipe. |
| 130 | envSyncPipe := os.Getenv("_LIBCONTAINER_SYNCPIPE") |
| 131 | syncPipeFd, err := strconv.Atoi(envSyncPipe) |
| 132 | if err != nil { |
| 133 | return fmt.Errorf("unable to convert _LIBCONTAINER_SYNCPIPE: %w", err) |
| 134 | } |
| 135 | syncPipe := newSyncSocket(os.NewFile(uintptr(syncPipeFd), "sync")) |
| 136 | defer syncPipe.Close() |
| 137 | |
| 138 | defer func() { |
| 139 | // If this defer is ever called, this means initialization has failed. |
| 140 | // Send the error back to the parent process in the form of an initError |
| 141 | // if the sync socket has not been closed. |
| 142 | if syncPipe.isClosed() { |
| 143 | return |
| 144 | } |
| 145 | ierr := initError{Message: retErr.Error()} |
| 146 | if err := writeSyncArg(syncPipe, procError, ierr); err != nil { |
| 147 | fmt.Fprintln(os.Stderr, err) |
| 148 | return |
| 149 | } |
| 150 | // The error is sent, no need to also return it (or it will be reported twice). |
| 151 | retErr = nil |
| 152 | }() |
| 153 | |
| 154 | // Get the INITPIPE. |
| 155 | envInitPipe := os.Getenv("_LIBCONTAINER_INITPIPE") |
| 156 | initPipeFd, err := strconv.Atoi(envInitPipe) |
| 157 | if err != nil { |
| 158 | return fmt.Errorf("unable to convert _LIBCONTAINER_INITPIPE: %w", err) |
| 159 | } |
| 160 | initPipe := os.NewFile(uintptr(initPipeFd), "init") |
| 161 | defer initPipe.Close() |
| 162 | |
| 163 | // Set up logging. This is used rarely, and mostly for init debugging. |
| 164 | |
| 165 | // Passing log level is optional; currently libcontainer/integration does not do it. |
| 166 | if levelStr := os.Getenv("_LIBCONTAINER_LOGLEVEL"); levelStr != "" { |
| 167 | logLevel, err := strconv.Atoi(levelStr) |
| 168 | if err != nil { |
| 169 | return fmt.Errorf("unable to convert _LIBCONTAINER_LOGLEVEL: %w", err) |
| 170 | } |
| 171 | logrus.SetLevel(logrus.Level(logLevel)) |
| 172 | } |
| 173 | |
| 174 | logFd, err := strconv.Atoi(os.Getenv("_LIBCONTAINER_LOGPIPE")) |
| 175 | if err != nil { |
| 176 | return fmt.Errorf("unable to convert _LIBCONTAINER_LOGPIPE: %w", err) |
| 177 | } |
| 178 | logPipe := os.NewFile(uintptr(logFd), "logpipe") |
| 179 | defer logPipe.Close() |
| 180 | |
| 181 | logrus.SetOutput(logPipe) |
| 182 | logrus.SetFormatter(new(logrus.JSONFormatter)) |
| 183 | logrus.Debug("child process in init()") |
| 184 | |
| 185 | // Only init processes have FIFOFD. |
no test coverage detected
searching dependent graphs…