Skip to content

Commit 5caea36

Browse files
authored
Merge pull request #1129 from Ace-Tang/gc_exec
feature: gc unused exec processes
2 parents 54eed7d + 9fb027e commit 5caea36

File tree

4 files changed

+79
-0
lines changed

4 files changed

+79
-0
lines changed

daemon/mgr/container.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ func NewContainerManager(ctx context.Context, store *meta.Store, cli ctrd.APICli
150150
mgr.Client.SetExitHooks(mgr.exitedAndRelease)
151151
mgr.Client.SetExecExitHooks(mgr.execExitedAndRelease)
152152

153+
go mgr.execProcessGC()
154+
153155
return mgr, mgr.Restore(ctx)
154156
}
155157

@@ -1742,3 +1744,32 @@ func (mgr *ContainerManager) setBaseFS(ctx context.Context, meta *ContainerMeta,
17421744
// io.containerd.runtime.v1.linux as a const used by runc
17431745
meta.BaseFS = filepath.Join(mgr.Config.HomeDir, "containerd/state", "io.containerd.runtime.v1.linux", namespaces.Default, info.Name, "rootfs")
17441746
}
1747+
1748+
// execProcessGC cleans unused exec processes config every 5 minutes.
1749+
func (mgr *ContainerManager) execProcessGC() {
1750+
for range time.Tick(time.Duration(GCExecProcessTick) * time.Minute) {
1751+
execProcesses := mgr.ExecProcesses.Values()
1752+
cleaned := 0
1753+
1754+
for id, v := range execProcesses {
1755+
execConfig, ok := v.(*ContainerExecConfig)
1756+
if !ok {
1757+
logrus.Warnf("get incorrect exec config: %v", v)
1758+
continue
1759+
}
1760+
// if unused exec processes are found, we will tag them, and clean
1761+
// them in next loop, so that we can ensure exec process can get
1762+
// correct exit code.
1763+
if execConfig.WaitForClean {
1764+
cleaned++
1765+
mgr.ExecProcesses.Remove(id)
1766+
} else if !execConfig.Running {
1767+
execConfig.WaitForClean = true
1768+
}
1769+
}
1770+
1771+
if cleaned > 0 {
1772+
logrus.Debugf("clean %d unused exec process", cleaned)
1773+
}
1774+
}
1775+
}

daemon/mgr/container_types.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ import (
1515
"github.com/opencontainers/image-spec/specs-go/v1"
1616
)
1717

18+
var (
19+
// GCExecProcessTick is the time interval to trigger gc unused exec config,
20+
// time unit is minute.
21+
GCExecProcessTick = 5
22+
)
23+
1824
const (
1925
// DefaultStopTimeout is the timeout (in seconds) for the syscall signal used to stop a container.
2026
DefaultStopTimeout = 10
@@ -43,6 +49,9 @@ type ContainerExecConfig struct {
4349

4450
// Error represents the exec process response error.
4551
Error error
52+
53+
// WaitForClean means exec process can be removed.
54+
WaitForClean bool
4655
}
4756

4857
// AttachConfig wraps some infos of attaching.

pkg/collect/safe_map.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,28 @@ func (m *SafeMap) Get(k string) *Value {
2525
return &Value{v, ok}
2626
}
2727

28+
// Values returns all key-values stored in map
29+
func (m *SafeMap) Values() map[string]interface{} {
30+
m.RLock()
31+
defer m.RUnlock()
32+
33+
nmap := make(map[string]interface{})
34+
for k, v := range m.inner {
35+
nmap[k] = v
36+
}
37+
38+
return nmap
39+
}
40+
2841
// Put stores a key-value pair into inner map safely.
2942
func (m *SafeMap) Put(k string, v interface{}) {
3043
m.Lock()
3144
defer m.Unlock()
45+
46+
if m.inner == nil {
47+
return
48+
}
49+
3250
m.inner[k] = v
3351
}
3452

pkg/collect/safe_map_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,27 @@ func TestSafeMapPutAndGet(t *testing.T) {
5050
assert.Equal(t, value.data, []string{"asdfgh", "123344"})
5151
}
5252

53+
// TestSafeMapDirectNew test functions should not panic.
54+
func TestSafeMapDirectNew(t *testing.T) {
55+
assert := assert.New(t)
56+
defer func() {
57+
if err := recover(); err != nil {
58+
t.Fatal(err)
59+
}
60+
}()
61+
62+
sm := &SafeMap{}
63+
// test Put not panic
64+
sm.Put("k", "v")
65+
66+
// test Remove not panic
67+
sm.Remove("k")
68+
69+
// test Values not panic
70+
values := sm.Values()
71+
assert.Equal(values, map[string]interface{}{})
72+
}
73+
5374
func TestSafeMapRemove(t *testing.T) {
5475
safeMap := NewSafeMap()
5576
assert.Equal(t, len(safeMap.inner), 0)

0 commit comments

Comments
 (0)