@@ -2,6 +2,8 @@ package hcs
22
33import (
44 "encoding/json"
5+ "os"
6+ "strconv"
57 "sync"
68 "syscall"
79 "time"
@@ -13,8 +15,29 @@ import (
1315
1416var (
1517 defaultTimeout = time .Minute * 4
18+
19+ // currentContainerStarts is used to limit the number of concurrent container
20+ // starts.
21+ currentContainerStarts containerStarts
1622)
1723
24+ type containerStarts struct {
25+ maxParallel int
26+ inProgress int
27+ sync.Mutex
28+ }
29+
30+ func init () {
31+ mpsS := os .Getenv ("HCSSHIM_MAX_PARALLEL_START" )
32+ if len (mpsS ) > 0 {
33+ mpsI , err := strconv .Atoi (mpsS )
34+ if err != nil || mpsI < 0 {
35+ return
36+ }
37+ currentContainerStarts .maxParallel = mpsI
38+ }
39+ }
40+
1841type System struct {
1942 handleLock sync.RWMutex
2043 handle hcsSystem
@@ -145,6 +168,32 @@ func (computeSystem *System) Start() error {
145168 return makeSystemError (computeSystem , "Start" , "" , ErrAlreadyClosed , nil )
146169 }
147170
171+ // This is a very simple backoff-retry loop to limit the number
172+ // of parallel container starts if environment variable
173+ // HCSSHIM_MAX_PARALLEL_START is set to a positive integer.
174+ // It should generally only be used as a workaround to various
175+ // platform issues that exist between RS1 and RS4 as of Aug 2018
176+ if currentContainerStarts .maxParallel > 0 {
177+ for {
178+ currentContainerStarts .Lock ()
179+ if currentContainerStarts .inProgress < currentContainerStarts .maxParallel {
180+ currentContainerStarts .inProgress ++
181+ currentContainerStarts .Unlock ()
182+ break
183+ }
184+ if currentContainerStarts .inProgress == currentContainerStarts .maxParallel {
185+ currentContainerStarts .Unlock ()
186+ time .Sleep (100 * time .Millisecond )
187+ }
188+ }
189+ // Make sure we decrement the count when we are done.
190+ defer func () {
191+ currentContainerStarts .Lock ()
192+ currentContainerStarts .inProgress --
193+ currentContainerStarts .Unlock ()
194+ }()
195+ }
196+
148197 var resultp * uint16
149198 err := hcsStartComputeSystem (computeSystem .handle , "" , & resultp )
150199 events , err := processAsyncHcsResult (err , resultp , computeSystem .callbackNumber , hcsNotificationSystemStartCompleted , & defaultTimeout )
0 commit comments