|
4 | 4 | "encoding/json" |
5 | 5 | "fmt" |
6 | 6 | "os" |
| 7 | + "strconv" |
7 | 8 | "sync" |
8 | 9 | "syscall" |
9 | 10 | "time" |
@@ -136,8 +137,26 @@ type ResourceModificationRequestResponse struct { |
136 | 137 | // is merged in the CreateContainer call to HCS. |
137 | 138 | var createContainerAdditionalJSON string |
138 | 139 |
|
| 140 | +// currentContainerStarts is used to limit the number of concurrent container |
| 141 | +// starts. |
| 142 | +var currentContainerStarts containerStarts |
| 143 | + |
| 144 | +type containerStarts struct { |
| 145 | + maxParallel int |
| 146 | + inProgress int |
| 147 | + sync.Mutex |
| 148 | +} |
| 149 | + |
139 | 150 | func init() { |
140 | 151 | createContainerAdditionalJSON = os.Getenv("HCSSHIM_CREATECONTAINER_ADDITIONALJSON") |
| 152 | + mpsS := os.Getenv("HCSSHIM_MAX_PARALLEL_START") |
| 153 | + if len(mpsS) > 0 { |
| 154 | + mpsI, err := strconv.Atoi(mpsS) |
| 155 | + if err != nil || mpsI < 0 { |
| 156 | + return |
| 157 | + } |
| 158 | + currentContainerStarts.maxParallel = mpsI |
| 159 | + } |
141 | 160 | } |
142 | 161 |
|
143 | 162 | // CreateContainer creates a new container with the given configuration but does not start it. |
@@ -325,6 +344,32 @@ func (container *container) Start() error { |
325 | 344 | return makeContainerError(container, operation, "", ErrAlreadyClosed) |
326 | 345 | } |
327 | 346 |
|
| 347 | + // This is a very simple backoff-retry loop to limit the number |
| 348 | + // of parallel container starts if environment variable |
| 349 | + // HCSSHIM_MAX_PARALLEL_START is set to a positive integer. |
| 350 | + // It should generally only be used as a workaround to various |
| 351 | + // platform issues that exist between RS1 and RS4 as of Aug 2018. |
| 352 | + if currentContainerStarts.maxParallel > 0 { |
| 353 | + for { |
| 354 | + currentContainerStarts.Lock() |
| 355 | + if currentContainerStarts.inProgress < currentContainerStarts.maxParallel { |
| 356 | + currentContainerStarts.inProgress++ |
| 357 | + currentContainerStarts.Unlock() |
| 358 | + break |
| 359 | + } |
| 360 | + if currentContainerStarts.inProgress == currentContainerStarts.maxParallel { |
| 361 | + currentContainerStarts.Unlock() |
| 362 | + time.Sleep(100 * time.Millisecond) |
| 363 | + } |
| 364 | + } |
| 365 | + // Make sure we decrement the count when we are done. |
| 366 | + defer func() { |
| 367 | + currentContainerStarts.Lock() |
| 368 | + currentContainerStarts.inProgress-- |
| 369 | + currentContainerStarts.Unlock() |
| 370 | + }() |
| 371 | + } |
| 372 | + |
328 | 373 | var resultp *uint16 |
329 | 374 | err := hcsStartComputeSystem(container.handle, "", &resultp) |
330 | 375 | err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemStartCompleted, &defaultTimeout) |
|
0 commit comments