diff options
author | Michał Zieliński <michal@zielinscy.org.pl> | 2018-04-16 20:02:26 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-04-16 20:02:26 +0200 |
commit | b2060acbc49ccface03a2350bf1c2e9ad456a75d (patch) | |
tree | 94e009771123efd276fc391899d5eda0bcb769ce | |
parent | 412cd61dabe160708c502e37a48b9c3c7c2c6017 (diff) | |
download | Nim-b2060acbc49ccface03a2350bf1c2e9ad456a75d.tar.gz |
osproc: fix double close on POSIX (#5724)
Calling close() in some cases issued two close() syscalls to one FD, which is incorrect in multithreaded programs.
-rw-r--r-- | lib/pure/osproc.nim | 20 | ||||
-rw-r--r-- | tests/osproc/tclose.nim | 24 |
2 files changed, 38 insertions, 6 deletions
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 555626514..a51b1f5ab 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -1001,13 +1001,21 @@ elif not defined(useNimRtl): {.pop} proc close(p: Process) = - if p.inStream != nil: close(p.inStream) - if p.outStream != nil: close(p.outStream) - if p.errStream != nil: close(p.errStream) if poParentStreams notin p.options: - discard close(p.inHandle) - discard close(p.outHandle) - discard close(p.errHandle) + if p.inStream != nil: + close(p.inStream) + else: + discard close(p.inHandle) + + if p.outStream != nil: + close(p.outStream) + else: + discard close(p.outHandle) + + if p.errStream != nil: + close(p.errStream) + else: + discard close(p.errHandle) proc suspend(p: Process) = if kill(p.id, SIGSTOP) != 0'i32: raiseOsError(osLastError()) diff --git a/tests/osproc/tclose.nim b/tests/osproc/tclose.nim new file mode 100644 index 000000000..d466b466a --- /dev/null +++ b/tests/osproc/tclose.nim @@ -0,0 +1,24 @@ +discard """ + exitcode: 0 +""" + +when defined(linux): + import osproc, os + + proc countFds(): int = + result = 0 + for i in walkDir("/proc/self/fd"): + result += 1 + + let initCount = countFds() + + let p = osproc.startProcess("echo", options={poUsePath}) + assert countFds() == initCount + 3 + p.close + assert countFds() == initCount + + let p1 = osproc.startProcess("echo", options={poUsePath}) + discard p1.inputStream + assert countFds() == initCount + 3 + p.close + assert countFds() == initCount |