@@ -62,28 +62,60 @@ import "C"
62
62
// compareStatus is used to confirm the contents of the thread
63
63
// specific status files match expectations.
64
64
func compareStatus (filter , expect string ) error {
65
- expected := filter + " \t " + expect
65
+ expected := filter + expect
66
66
pid := syscall .Getpid ()
67
67
fs , err := ioutil .ReadDir (fmt .Sprintf ("/proc/%d/task" , pid ))
68
68
if err != nil {
69
69
return fmt .Errorf ("unable to find %d tasks: %v" , pid , err )
70
70
}
71
+ expectedProc := fmt .Sprintf ("Pid:\t %d" , pid )
72
+ foundAThread := false
71
73
for _ , f := range fs {
72
74
tf := fmt .Sprintf ("/proc/%s/status" , f .Name ())
73
75
d , err := ioutil .ReadFile (tf )
74
76
if err != nil {
75
- return fmt .Errorf ("unable to read %q: %v" , tf , err )
77
+ // There are a surprising number of ways this
78
+ // can error out on linux. We've seen all of
79
+ // the following, so treat any error here as
80
+ // equivalent to the "process is gone":
81
+ // os.IsNotExist(err),
82
+ // "... : no such process",
83
+ // "... : bad file descriptor.
84
+ continue
76
85
}
77
86
lines := strings .Split (string (d ), "\n " )
78
87
for _ , line := range lines {
88
+ // Different kernel vintages pad differently.
89
+ line = strings .TrimSpace (line )
90
+ if strings .HasPrefix (line , "Pid:\t " ) {
91
+ // On loaded systems, it is possible
92
+ // for a TID to be reused really
93
+ // quickly. As such, we need to
94
+ // validate that the thread status
95
+ // info we just read is a task of the
96
+ // same process PID as we are
97
+ // currently running, and not a
98
+ // recently terminated thread
99
+ // resurfaced in a different process.
100
+ if line != expectedProc {
101
+ break
102
+ }
103
+ // Fall through in the unlikely case
104
+ // that filter at some point is
105
+ // "Pid:\t".
106
+ }
79
107
if strings .HasPrefix (line , filter ) {
80
108
if line != expected {
81
- return fmt .Errorf ("%s %s (bad)\n " , tf , line )
109
+ return fmt .Errorf ("%q got:%q want:%q (bad) [pid=%d file:'%s' %v] \n " , tf , line , expected , pid , string ( d ), expectedProc )
82
110
}
111
+ foundAThread = true
83
112
break
84
113
}
85
114
}
86
115
}
116
+ if ! foundAThread {
117
+ return fmt .Errorf ("found no thread /proc/<TID>/status files for process %q" , expectedProc )
118
+ }
87
119
return nil
88
120
}
89
121
@@ -110,34 +142,34 @@ func test1435(t *testing.T) {
110
142
fn func () error
111
143
filter , expect string
112
144
}{
113
- {call : "Setegid(1)" , fn : func () error { return syscall .Setegid (1 ) }, filter : "Gid:" , expect : "0 \t 1\t 0\t 1" },
114
- {call : "Setegid(0)" , fn : func () error { return syscall .Setegid (0 ) }, filter : "Gid:" , expect : "0 \t 0\t 0\t 0" },
145
+ {call : "Setegid(1)" , fn : func () error { return syscall .Setegid (1 ) }, filter : "Gid:" , expect : "\t 0 \t 1\t 0\t 1" },
146
+ {call : "Setegid(0)" , fn : func () error { return syscall .Setegid (0 ) }, filter : "Gid:" , expect : "\t 0 \t 0\t 0\t 0" },
115
147
116
- {call : "Seteuid(1)" , fn : func () error { return syscall .Seteuid (1 ) }, filter : "Uid:" , expect : "0 \t 1\t 0\t 1" },
117
- {call : "Setuid(0)" , fn : func () error { return syscall .Setuid (0 ) }, filter : "Uid:" , expect : "0 \t 0\t 0\t 0" },
148
+ {call : "Seteuid(1)" , fn : func () error { return syscall .Seteuid (1 ) }, filter : "Uid:" , expect : "\t 0 \t 1\t 0\t 1" },
149
+ {call : "Setuid(0)" , fn : func () error { return syscall .Setuid (0 ) }, filter : "Uid:" , expect : "\t 0 \t 0\t 0\t 0" },
118
150
119
- {call : "Setgid(1)" , fn : func () error { return syscall .Setgid (1 ) }, filter : "Gid:" , expect : "1 \t 1\t 1\t 1" },
120
- {call : "Setgid(0)" , fn : func () error { return syscall .Setgid (0 ) }, filter : "Gid:" , expect : "0 \t 0\t 0\t 0" },
151
+ {call : "Setgid(1)" , fn : func () error { return syscall .Setgid (1 ) }, filter : "Gid:" , expect : "\t 1 \t 1\t 1\t 1" },
152
+ {call : "Setgid(0)" , fn : func () error { return syscall .Setgid (0 ) }, filter : "Gid:" , expect : "\t 0 \t 0\t 0\t 0" },
121
153
122
- {call : "Setgroups([]int{0,1,2,3})" , fn : func () error { return syscall .Setgroups ([]int {0 , 1 , 2 , 3 }) }, filter : "Groups:" , expect : "0 1 2 3 " },
123
- {call : "Setgroups(nil)" , fn : func () error { return syscall .Setgroups (nil ) }, filter : "Groups:" , expect : " " },
124
- {call : "Setgroups([]int{0})" , fn : func () error { return syscall .Setgroups ([]int {0 }) }, filter : "Groups:" , expect : "0 " },
154
+ {call : "Setgroups([]int{0,1,2,3})" , fn : func () error { return syscall .Setgroups ([]int {0 , 1 , 2 , 3 }) }, filter : "Groups:" , expect : "\t 0 1 2 3" },
155
+ {call : "Setgroups(nil)" , fn : func () error { return syscall .Setgroups (nil ) }, filter : "Groups:" , expect : "" },
156
+ {call : "Setgroups([]int{0})" , fn : func () error { return syscall .Setgroups ([]int {0 }) }, filter : "Groups:" , expect : "\t 0 " },
125
157
126
- {call : "Setregid(101,0)" , fn : func () error { return syscall .Setregid (101 , 0 ) }, filter : "Gid:" , expect : "101 \t 0\t 0\t 0" },
127
- {call : "Setregid(0,102)" , fn : func () error { return syscall .Setregid (0 , 102 ) }, filter : "Gid:" , expect : "0 \t 102\t 102\t 102" },
128
- {call : "Setregid(0,0)" , fn : func () error { return syscall .Setregid (0 , 0 ) }, filter : "Gid:" , expect : "0 \t 0\t 0\t 0" },
158
+ {call : "Setregid(101,0)" , fn : func () error { return syscall .Setregid (101 , 0 ) }, filter : "Gid:" , expect : "\t 101 \t 0\t 0\t 0" },
159
+ {call : "Setregid(0,102)" , fn : func () error { return syscall .Setregid (0 , 102 ) }, filter : "Gid:" , expect : "\t 0 \t 102\t 102\t 102" },
160
+ {call : "Setregid(0,0)" , fn : func () error { return syscall .Setregid (0 , 0 ) }, filter : "Gid:" , expect : "\t 0 \t 0\t 0\t 0" },
129
161
130
- {call : "Setreuid(1,0)" , fn : func () error { return syscall .Setreuid (1 , 0 ) }, filter : "Uid:" , expect : "1 \t 0\t 0\t 0" },
131
- {call : "Setreuid(0,2)" , fn : func () error { return syscall .Setreuid (0 , 2 ) }, filter : "Uid:" , expect : "0 \t 2\t 2\t 2" },
132
- {call : "Setreuid(0,0)" , fn : func () error { return syscall .Setreuid (0 , 0 ) }, filter : "Uid:" , expect : "0 \t 0\t 0\t 0" },
162
+ {call : "Setreuid(1,0)" , fn : func () error { return syscall .Setreuid (1 , 0 ) }, filter : "Uid:" , expect : "\t 1 \t 0\t 0\t 0" },
163
+ {call : "Setreuid(0,2)" , fn : func () error { return syscall .Setreuid (0 , 2 ) }, filter : "Uid:" , expect : "\t 0 \t 2\t 2\t 2" },
164
+ {call : "Setreuid(0,0)" , fn : func () error { return syscall .Setreuid (0 , 0 ) }, filter : "Uid:" , expect : "\t 0 \t 0\t 0\t 0" },
133
165
134
- {call : "Setresgid(101,0,102)" , fn : func () error { return syscall .Setresgid (101 , 0 , 102 ) }, filter : "Gid:" , expect : "101 \t 0\t 102\t 0" },
135
- {call : "Setresgid(0,102,101)" , fn : func () error { return syscall .Setresgid (0 , 102 , 101 ) }, filter : "Gid:" , expect : "0 \t 102\t 101\t 102" },
136
- {call : "Setresgid(0,0,0)" , fn : func () error { return syscall .Setresgid (0 , 0 , 0 ) }, filter : "Gid:" , expect : "0 \t 0\t 0\t 0" },
166
+ {call : "Setresgid(101,0,102)" , fn : func () error { return syscall .Setresgid (101 , 0 , 102 ) }, filter : "Gid:" , expect : "\t 101 \t 0\t 102\t 0" },
167
+ {call : "Setresgid(0,102,101)" , fn : func () error { return syscall .Setresgid (0 , 102 , 101 ) }, filter : "Gid:" , expect : "\t 0 \t 102\t 101\t 102" },
168
+ {call : "Setresgid(0,0,0)" , fn : func () error { return syscall .Setresgid (0 , 0 , 0 ) }, filter : "Gid:" , expect : "\t 0 \t 0\t 0\t 0" },
137
169
138
- {call : "Setresuid(1,0,2)" , fn : func () error { return syscall .Setresuid (1 , 0 , 2 ) }, filter : "Uid:" , expect : "1 \t 0\t 2\t 0" },
139
- {call : "Setresuid(0,2,1)" , fn : func () error { return syscall .Setresuid (0 , 2 , 1 ) }, filter : "Uid:" , expect : "0 \t 2\t 1\t 2" },
140
- {call : "Setresuid(0,0,0)" , fn : func () error { return syscall .Setresuid (0 , 0 , 0 ) }, filter : "Uid:" , expect : "0 \t 0\t 0\t 0" },
170
+ {call : "Setresuid(1,0,2)" , fn : func () error { return syscall .Setresuid (1 , 0 , 2 ) }, filter : "Uid:" , expect : "\t 1 \t 0\t 2\t 0" },
171
+ {call : "Setresuid(0,2,1)" , fn : func () error { return syscall .Setresuid (0 , 2 , 1 ) }, filter : "Uid:" , expect : "\t 0 \t 2\t 1\t 2" },
172
+ {call : "Setresuid(0,0,0)" , fn : func () error { return syscall .Setresuid (0 , 0 , 0 ) }, filter : "Uid:" , expect : "\t 0 \t 0\t 0\t 0" },
141
173
}
142
174
143
175
for i , v := range vs {
0 commit comments