Fix linux start process errorCode always 0 (#24001)

#23992 The test case provided does not cover the Windows situation, I
fixed it in this new PR.

Fixed an issue where errorCode was always 0 when startProcess didn't use
the poEvalCommand flag.

Tthe sleep command might not be available in all Windows installations,
so I skipped the relevant test.

Added a test case, tested on my fedora and windows systems.
This commit is contained in:
握猫猫
2024-08-29 02:52:00 +08:00
committed by GitHub
parent 770f8d5513
commit 5e8cd318ef
3 changed files with 49 additions and 14 deletions

View File

@@ -1123,14 +1123,13 @@ elif not defined(useNimRtl):
var error: cint
let sizeRead = read(data.pErrorPipe[readIdx], addr error, sizeof(error))
if sizeRead == sizeof(error):
raiseOSError(osLastError(),
raiseOSError(OSErrorCode(error),
"Could not find command: '" & $data.sysCommand & "'. OS error: " & $strerror(error))
return pid
{.push stacktrace: off, profiler: off.}
proc startProcessFail(data: ptr StartProcessData) =
var error: cint = errno
proc startProcessFail(data: ptr StartProcessData, error: cint = errno) =
discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error))
exitnow(1)
@@ -1167,7 +1166,11 @@ elif not defined(useNimRtl):
if (poUsePath in data.options):
when defined(uClibc) or defined(linux) or defined(haiku):
# uClibc environment (OpenWrt included) doesn't have the full execvpe
let exe = findExe(data.sysCommand)
var exe: string
try:
exe = findExe(data.sysCommand)
except OSError as e:
startProcessFail(data, e.errorCode)
discard execve(exe.cstring, data.sysArgs, data.sysEnv)
else:
# MacOSX doesn't have execvpe, so we need workaround.

27
tests/osproc/tnoexe.nim Normal file
View File

@@ -0,0 +1,27 @@
discard """
output: '''true
true'''
"""
import std/osproc
const command = "lsaaa -lah"
try:
let process = startProcess(command, options = {poUsePath})
discard process.waitForExit()
except OSError as e:
echo e.errorCode != 0
# `poEvalCommand`, invokes the system shell to run the specified command
try:
let process = startProcess(command, options = {poUsePath, poEvalCommand})
# linux
let exitCode = process.waitForExit()
echo exitCode != 0
except OSError as e:
# Because the implementation of `poEvalCommand` on different platforms is inconsistent,
# Linux will not throw an exception, but Windows will throw an exception
# windows
echo e.errorCode != 0

View File

@@ -18,16 +18,21 @@ block: # bug #5091
doAssert(getTime() < atStart + milliseconds(msWait))
block: # bug #23825
var thr: array[0..99, Thread[int]]
proc threadFunc(i: int) {.thread.} =
let sleepTime = float(i) / float(thr.len + 1)
doAssert sleepTime < 1.0
let p = startProcess("sleep", workingDir = "", args = @[$sleepTime], options = {poUsePath, poParentStreams})
# timeout = 1_000_000 seconds ~= 278 hours ~= 11.5 days
doAssert p.waitForExit(timeout=1_000_000_000) == 0
# the sleep command might not be available in all Windows installations
for i in low(thr)..high(thr):
createThread(thr[i], threadFunc, i)
when defined(linux):
joinThreads(thr)
var thr: array[0..99, Thread[int]]
proc threadFunc(i: int) {.thread.} =
let sleepTime = float(i) / float(thr.len + 1)
doAssert sleepTime < 1.0
let p = startProcess("sleep", workingDir = "", args = @[$sleepTime], options = {poUsePath, poParentStreams})
# timeout = 1_000_000 seconds ~= 278 hours ~= 11.5 days
doAssert p.waitForExit(timeout=1_000_000_000) == 0
for i in low(thr)..high(thr):
createThread(thr[i], threadFunc, i)
joinThreads(thr)