diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index bd6bcde2be..c304ecca64 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -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. diff --git a/tests/osproc/tnoexe.nim b/tests/osproc/tnoexe.nim new file mode 100644 index 0000000000..19a3cca676 --- /dev/null +++ b/tests/osproc/tnoexe.nim @@ -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 diff --git a/tests/osproc/twaitforexit.nim b/tests/osproc/twaitforexit.nim index 67caa41659..535faca637 100644 --- a/tests/osproc/twaitforexit.nim +++ b/tests/osproc/twaitforexit.nim @@ -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)