Make 'echo' raise IOErrors when appropriate (#16367)
* Make 'echo' raise IOError when fwrite/fflush fail * Fix fwrite return value comparison * Add test for echo raising error and don't fail to release locks in echo * Fix exitcode expectation * Make 'echo' raise IOError on Windows if it fails * Add nimLegacyEchoNoRaise for prior no-IOError echo behavior * Use checkErrMaybe template
This commit is contained in:
parent
df17cf5e9e
commit
23d23ecb08
3 changed files with 30 additions and 8 deletions
|
|
@ -63,6 +63,9 @@
|
||||||
|
|
||||||
- Added `math.isNaN`.
|
- Added `math.isNaN`.
|
||||||
|
|
||||||
|
- `echo` and `debugEcho` will now raise `IOError` if writing to stdout fails. Previous behavior
|
||||||
|
silently ignored errors. See #16366. Use `-d:nimLegacyEchoNoRaise` for previous behavior.
|
||||||
|
|
||||||
## Language changes
|
## Language changes
|
||||||
|
|
||||||
- `nimscript` now handles `except Exception as e`.
|
- `nimscript` now handles `except Exception as e`.
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,9 @@ when defined(windows):
|
||||||
# But we cannot call printf directly as the string might contain \0.
|
# But we cannot call printf directly as the string might contain \0.
|
||||||
# So we have to loop over all the sections separated by potential \0s.
|
# So we have to loop over all the sections separated by potential \0s.
|
||||||
var i = c_fprintf(f, "%s", s)
|
var i = c_fprintf(f, "%s", s)
|
||||||
|
if i < 0:
|
||||||
|
if doRaise: raiseEIO("cannot write string to file")
|
||||||
|
return
|
||||||
while i < s.len:
|
while i < s.len:
|
||||||
if s[i] == '\0':
|
if s[i] == '\0':
|
||||||
let w = c_fputc('\0', f)
|
let w = c_fputc('\0', f)
|
||||||
|
|
@ -780,6 +783,13 @@ when declared(stdout):
|
||||||
not defined(nintendoswitch) and not defined(freertos) and
|
not defined(nintendoswitch) and not defined(freertos) and
|
||||||
hostOS != "any"
|
hostOS != "any"
|
||||||
|
|
||||||
|
const echoDoRaise = not defined(nimLegacyEchoNoRaise) # see PR #16366
|
||||||
|
|
||||||
|
template checkErrMaybe(succeeded: bool): untyped =
|
||||||
|
if not succeeded:
|
||||||
|
when echoDoRaise:
|
||||||
|
checkErr(stdout)
|
||||||
|
|
||||||
proc echoBinSafe(args: openArray[string]) {.compilerproc.} =
|
proc echoBinSafe(args: openArray[string]) {.compilerproc.} =
|
||||||
when defined(androidNDK):
|
when defined(androidNDK):
|
||||||
var s = ""
|
var s = ""
|
||||||
|
|
@ -792,20 +802,18 @@ when declared(stdout):
|
||||||
proc flockfile(f: File) {.importc, nodecl.}
|
proc flockfile(f: File) {.importc, nodecl.}
|
||||||
proc funlockfile(f: File) {.importc, nodecl.}
|
proc funlockfile(f: File) {.importc, nodecl.}
|
||||||
flockfile(stdout)
|
flockfile(stdout)
|
||||||
|
defer: funlockfile(stdout)
|
||||||
when defined(windows) and compileOption("threads"):
|
when defined(windows) and compileOption("threads"):
|
||||||
acquireSys echoLock
|
acquireSys echoLock
|
||||||
|
defer: releaseSys echoLock
|
||||||
for s in args:
|
for s in args:
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
writeWindows(stdout, s)
|
writeWindows(stdout, s, doRaise = echoDoRaise)
|
||||||
else:
|
else:
|
||||||
discard c_fwrite(s.cstring, cast[csize_t](s.len), 1, stdout)
|
checkErrMaybe(c_fwrite(s.cstring, cast[csize_t](s.len), 1, stdout) == s.len)
|
||||||
const linefeed = "\n"
|
const linefeed = "\n"
|
||||||
discard c_fwrite(linefeed.cstring, linefeed.len, 1, stdout)
|
checkErrMaybe(c_fwrite(linefeed.cstring, linefeed.len, 1, stdout) == linefeed.len)
|
||||||
discard c_fflush(stdout)
|
checkErrMaybe(c_fflush(stdout) == 0)
|
||||||
when stdOutLock:
|
|
||||||
funlockfile(stdout)
|
|
||||||
when defined(windows) and compileOption("threads"):
|
|
||||||
releaseSys echoLock
|
|
||||||
|
|
||||||
|
|
||||||
when defined(windows) and not defined(nimscript) and not defined(js):
|
when defined(windows) and not defined(nimscript) and not defined(js):
|
||||||
|
|
|
||||||
11
tests/exception/t16366.nim
Normal file
11
tests/exception/t16366.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
discard """
|
||||||
|
action: run
|
||||||
|
exitcode: 0
|
||||||
|
targets: "c cpp"
|
||||||
|
disabled: openbsd
|
||||||
|
"""
|
||||||
|
|
||||||
|
echo "foo1"
|
||||||
|
close stdout
|
||||||
|
doAssertRaises(IOError):
|
||||||
|
echo "foo"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue