Skip to content

Commit d662648

Browse files
committed
[GR-26827] Fixed file descriptor leaks by closing Selector
PullRequest: graalpython/1339
2 parents dc1a599 + f45909e commit d662648

File tree

4 files changed

+58
-52
lines changed

4 files changed

+58
-52
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_tagged_unittests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def parse_unittest_output(output):
208208

209209
# n.b.: we add a '*' in the front, so that unittests doesn't add
210210
# its own asterisks, because now this is already a pattern
211-
for funcname, classname, result in parse_unittest_output(stderr):
211+
for funcname, classname, result in parse_unittest_output(p.stderr):
212212
# We consider skipped tests as passing in order to avoid a situation where a Linux run
213213
# untags a Darwin-only test and vice versa
214214
if result == 'ok' or result.startswith('skipped'):

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,13 +1449,8 @@ PTuple waitpid(VirtualFrame frame, int pid, int options) {
14491449
int exitStatus = getResources().waitpid(pid);
14501450
return factory().createTuple(new Object[]{pid, exitStatus});
14511451
} else if (options == WNOHANG) {
1452-
int exitStatus = getResources().exitStatus(pid);
1453-
if (exitStatus == Integer.MIN_VALUE) {
1454-
// not terminated, yet, we should return 0
1455-
return factory().createTuple(new Object[]{0, 0});
1456-
} else {
1457-
return factory().createTuple(new Object[]{pid, exitStatus});
1458-
}
1452+
int[] res = getResources().exitStatus(pid);
1453+
return factory().createTuple(new Object[]{res[0], res[1]});
14591454
} else {
14601455
throw raise(PythonBuiltinClassType.NotImplementedError, "Only 0 or WNOHANG are supported for waitpid");
14611456
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SelectModuleBuiltins.java

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -164,56 +164,57 @@ PTuple doGeneric(VirtualFrame frame, Object rlist, Object wlist, Object xlist, O
164164

165165
@TruffleBoundary
166166
private static void doSelect(ChannelFD[] readFDs, ChannelFD[] writeFDs, ChannelFD[] xFDs, long timeoutMillis) throws IOException {
167-
Selector selector = Selector.open();
167+
try (Selector selector = Selector.open()) {
168168

169-
for (ChannelFD readFD : readFDs) {
170-
readFD.channel.configureBlocking(false);
171-
readFD.channel.register(selector, SelectionKey.OP_READ);
172-
}
169+
for (ChannelFD readFD : readFDs) {
170+
readFD.channel.configureBlocking(false);
171+
readFD.channel.register(selector, SelectionKey.OP_READ);
172+
}
173173

174-
for (ChannelFD writeFD : writeFDs) {
175-
writeFD.channel.configureBlocking(false);
176-
writeFD.channel.register(selector, SelectionKey.OP_WRITE);
177-
}
174+
for (ChannelFD writeFD : writeFDs) {
175+
writeFD.channel.configureBlocking(false);
176+
writeFD.channel.register(selector, SelectionKey.OP_WRITE);
177+
}
178178

179-
for (ChannelFD xFD : xFDs) {
180-
// TODO(fa): not sure if these ops are representing
181-
// "exceptional condition pending"
182-
xFD.channel.configureBlocking(false);
183-
xFD.channel.register(selector, SelectionKey.OP_ACCEPT | SelectionKey.OP_CONNECT);
184-
}
179+
for (ChannelFD xFD : xFDs) {
180+
// TODO(fa): not sure if these ops are representing
181+
// "exceptional condition pending"
182+
xFD.channel.configureBlocking(false);
183+
xFD.channel.register(selector, SelectionKey.OP_ACCEPT | SelectionKey.OP_CONNECT);
184+
}
185185

186-
int selected = selector.select(timeoutMillis);
186+
int selected = selector.select(timeoutMillis);
187187

188-
// remove non-selected channels from given lists
189-
int deleted = 0;
190-
for (int i = 0; i < readFDs.length; i++) {
191-
ChannelFD readFD = readFDs[i];
192-
SelectionKey selectionKey = readFD.channel.keyFor(selector);
193-
if (!selectionKey.isReadable()) {
194-
readFDs[i] = null;
195-
deleted++;
188+
// remove non-selected channels from given lists
189+
int deleted = 0;
190+
for (int i = 0; i < readFDs.length; i++) {
191+
ChannelFD readFD = readFDs[i];
192+
SelectionKey selectionKey = readFD.channel.keyFor(selector);
193+
if (!selectionKey.isReadable()) {
194+
readFDs[i] = null;
195+
deleted++;
196+
}
196197
}
197-
}
198198

199-
for (int i = 0; i < writeFDs.length; i++) {
200-
ChannelFD writeFD = writeFDs[i];
201-
SelectionKey selectionKey = writeFD.channel.keyFor(selector);
202-
if (!selectionKey.isWritable()) {
203-
writeFDs[i] = null;
204-
deleted++;
199+
for (int i = 0; i < writeFDs.length; i++) {
200+
ChannelFD writeFD = writeFDs[i];
201+
SelectionKey selectionKey = writeFD.channel.keyFor(selector);
202+
if (!selectionKey.isWritable()) {
203+
writeFDs[i] = null;
204+
deleted++;
205+
}
205206
}
206-
}
207207

208-
for (int i = 0; i < xFDs.length; i++) {
209-
ChannelFD xFD = xFDs[i];
210-
SelectionKey selectionKey = xFD.channel.keyFor(selector);
211-
if (!(selectionKey.isAcceptable() || selectionKey.isConnectable())) {
212-
xFDs[i] = null;
213-
deleted++;
208+
for (int i = 0; i < xFDs.length; i++) {
209+
ChannelFD xFD = xFDs[i];
210+
SelectionKey selectionKey = xFD.channel.keyFor(selector);
211+
if (!(selectionKey.isAcceptable() || selectionKey.isConnectable())) {
212+
xFDs[i] = null;
213+
deleted++;
214+
}
214215
}
216+
assert selected == (readFDs.length + writeFDs.length + xFDs.length) - deleted;
215217
}
216-
assert selected == (readFDs.length + writeFDs.length + xFDs.length) - deleted;
217218
}
218219

219220
private ChannelFD[] seq2set(VirtualFrame frame, Object sequence, PythonObjectLibrary sequenceLib, PythonObjectLibrary itemLib, LookupAndCallBinaryNode callGetItemNode,

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixResources.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -458,13 +458,23 @@ public int waitpid(int pid) throws IndexOutOfBoundsException, InterruptedExcepti
458458
}
459459

460460
@TruffleBoundary(allowInlining = true)
461-
public int exitStatus(int pid) throws IndexOutOfBoundsException {
462-
Process process = getChild(pid);
463-
if (process.isAlive()) {
464-
return Integer.MIN_VALUE;
461+
public int[] exitStatus(int pid) throws IndexOutOfBoundsException {
462+
if (pid == -1) {
463+
for (int childPid = 1; childPid < children.size(); ++childPid) {
464+
Process child = children.get(childPid);
465+
if (child != null && !child.isAlive()) {
466+
children.set(childPid, null);
467+
return new int[]{childPid, child.exitValue()};
468+
}
469+
}
465470
} else {
466-
return process.exitValue();
471+
Process process = getChild(pid);
472+
if (!process.isAlive()) {
473+
children.set(pid, null);
474+
return new int[]{pid, process.exitValue()};
475+
}
467476
}
477+
return new int[]{0, 0};
468478
}
469479

470480
@TruffleBoundary(allowInlining = true)

0 commit comments

Comments
 (0)