Skip to content

Commit 693c957

Browse files
committed
pkg/cdi: add test case for post-EMFILE recovery.
Test that the cache indeed recovers functionally if the process ever recovers from not being able to create new file descriptors. Signed-off-by: Krisztian Litkey <[email protected]>
1 parent d0ccbf8 commit 693c957

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

pkg/cdi/cache_linux_test.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package cdi
1919
import (
2020
"fmt"
2121
"os"
22+
"path/filepath"
2223
"strconv"
2324
"strings"
2425
"syscall"
@@ -48,6 +49,100 @@ func TestTooManyOpenFiles(t *testing.T) {
4849
_, _ = cache.InjectDevices(&oci.Spec{}, "vendor1.com/device=dev1")
4950
}
5051

52+
func TestRecoveryAfterTooManyOpenFiles(t *testing.T) {
53+
var (
54+
etcDir = map[string]string{
55+
"vendor1.yaml": `
56+
cdiVersion: "0.3.0"
57+
kind: "vendor1.com/device"
58+
containerEdits:
59+
env:
60+
- VENDOR1_SPEC_VAR1=VAL1
61+
devices:
62+
- name: "dev1"
63+
containerEdits:
64+
env:
65+
- "VENDOR1_VAR1=VAL1"
66+
deviceNodes:
67+
- path: "/dev/vendor1-dev1"
68+
type: b
69+
major: 10
70+
minor: 1
71+
`,
72+
}
73+
74+
devices = []string{
75+
"vendor1.com/device=dev1",
76+
}
77+
78+
ociSpec = &oci.Spec{}
79+
80+
resultingSpec = &oci.Spec{
81+
Process: &oci.Process{
82+
Env: []string{
83+
"VENDOR1_SPEC_VAR1=VAL1",
84+
"VENDOR1_VAR1=VAL1",
85+
},
86+
},
87+
Linux: &oci.Linux{
88+
Devices: []oci.LinuxDevice{
89+
{
90+
Path: "/dev/vendor1-dev1",
91+
Type: "b",
92+
Major: 10,
93+
Minor: 1,
94+
},
95+
},
96+
Resources: &oci.LinuxResources{
97+
Devices: []oci.LinuxDeviceCgroup{
98+
{
99+
Allow: true,
100+
Type: "b",
101+
Major: int64ptr(10),
102+
Minor: int64ptr(1),
103+
Access: "rwm",
104+
},
105+
},
106+
},
107+
},
108+
}
109+
)
110+
111+
dir, err := createSpecDirs(t, etcDir, nil)
112+
require.NoError(t, err, "failed to create test directory")
113+
114+
// trigger EMFILE for fd creation: exhaust our file descriptor table
115+
em, err := triggerEmfile()
116+
require.NoError(t, err)
117+
require.NotNil(t, em)
118+
defer func() {
119+
require.NoError(t, em.undo())
120+
}()
121+
122+
_, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0)
123+
require.Equal(t, syscall.EMFILE, err)
124+
125+
cache := newCache(
126+
WithSpecDirs(
127+
filepath.Join(dir, "etc"),
128+
),
129+
WithAutoRefresh(true),
130+
)
131+
require.NotNil(t, cache)
132+
133+
// try to trigger original crash with a nil fsnotify.Watcher
134+
_, _ = cache.InjectDevices(&oci.Spec{}, devices...)
135+
136+
// undo EMFILE for fd creation
137+
require.NoError(t, em.undo())
138+
139+
// verify that injection works again
140+
unresolved, err := cache.InjectDevices(ociSpec, devices...)
141+
require.NoError(t, err)
142+
require.Nil(t, unresolved)
143+
require.Equal(t, resultingSpec, ociSpec)
144+
}
145+
51146
type emfile struct {
52147
limit syscall.Rlimit
53148
fds []int

0 commit comments

Comments
 (0)