More fixes for Haiku (#13774)

* osproc: move fork-based code path under the when conditional

* osproc: avoid using the environ global on Haiku

* osenv: import environ from stdlib.h on Haiku

Haiku's environ is declared in `<stdlib.h>` by default, differing from
POSIX and/or Linux. Import it from there to avoid collision with anyone
importing `<stdlib.h>` from Nim.
This commit is contained in:
alaviss 2020-03-27 08:08:13 +00:00 • committed by GitHub
commit 0eaacbc2c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 46 deletions

View file

@ -81,6 +81,8 @@ else:
# at runtime. # at runtime.
proc NSGetEnviron(): ptr cstringArray {. proc NSGetEnviron(): ptr cstringArray {.
importc: "_NSGetEnviron", header: "<crt_externs.h>".} importc: "_NSGetEnviron", header: "<crt_externs.h>".}
elif defined(haiku):
var gEnv {.importc: "environ", header: "<stdlib.h>".}: cstringArray
else: else:
var gEnv {.importc: "environ".}: cstringArray var gEnv {.importc: "environ".}: cstringArray

View file

@ -826,10 +826,10 @@ elif not defined(useNimRtl):
else: else:
proc startProcessAuxFork(data: StartProcessData): Pid {. proc startProcessAuxFork(data: StartProcessData): Pid {.
tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], gcsafe.} tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], gcsafe.}
{.push stacktrace: off, profiler: off.} {.push stacktrace: off, profiler: off.}
proc startProcessAfterFork(data: ptr StartProcessData) {. proc startProcessAfterFork(data: ptr StartProcessData) {.
tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], cdecl, gcsafe.} tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], cdecl, gcsafe.}
{.pop.} {.pop.}
proc startProcess(command: string, workingDir: string = "", proc startProcess(command: string, workingDir: string = "",
args: openArray[string] = [], env: StringTableRef = nil, args: openArray[string] = [], env: StringTableRef = nil,
@ -1003,56 +1003,57 @@ elif not defined(useNimRtl):
return pid return pid
{.push stacktrace: off, profiler: off.} {.push stacktrace: off, profiler: off.}
proc startProcessFail(data: ptr StartProcessData) = proc startProcessFail(data: ptr StartProcessData) =
var error: cint = errno var error: cint = errno
discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error)) discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error))
exitnow(1) exitnow(1)
when not defined(uClibc) and (not defined(linux) or defined(android)): when not defined(uClibc) and (not defined(linux) or defined(android)) and
var environ {.importc.}: cstringArray not defined(haiku):
var environ {.importc.}: cstringArray
proc startProcessAfterFork(data: ptr StartProcessData) = proc startProcessAfterFork(data: ptr StartProcessData) =
# Warning: no GC here! # Warning: no GC here!
# Or anything that touches global structures - all called nim procs # Or anything that touches global structures - all called nim procs
# must be marked with stackTrace:off. Inspect C code after making changes. # must be marked with stackTrace:off. Inspect C code after making changes.
if not (poParentStreams in data.options): if not (poParentStreams in data.options):
discard close(data.pStdin[writeIdx]) discard close(data.pStdin[writeIdx])
if dup2(data.pStdin[readIdx], readIdx) < 0: if dup2(data.pStdin[readIdx], readIdx) < 0:
startProcessFail(data)
discard close(data.pStdout[readIdx])
if dup2(data.pStdout[writeIdx], writeIdx) < 0:
startProcessFail(data)
discard close(data.pStderr[readIdx])
if (poStdErrToStdOut in data.options):
if dup2(data.pStdout[writeIdx], 2) < 0:
startProcessFail(data) startProcessFail(data)
else: discard close(data.pStdout[readIdx])
if dup2(data.pStderr[writeIdx], 2) < 0: if dup2(data.pStdout[writeIdx], writeIdx) < 0:
startProcessFail(data)
discard close(data.pStderr[readIdx])
if (poStdErrToStdOut in data.options):
if dup2(data.pStdout[writeIdx], 2) < 0:
startProcessFail(data)
else:
if dup2(data.pStderr[writeIdx], 2) < 0:
startProcessFail(data)
if data.workingDir.len > 0:
if chdir(data.workingDir) < 0:
startProcessFail(data) startProcessFail(data)
if data.workingDir.len > 0: discard close(data.pErrorPipe[readIdx])
if chdir(data.workingDir) < 0: discard fcntl(data.pErrorPipe[writeIdx], F_SETFD, FD_CLOEXEC)
startProcessFail(data)
discard close(data.pErrorPipe[readIdx]) if (poUsePath in data.options):
discard fcntl(data.pErrorPipe[writeIdx], F_SETFD, FD_CLOEXEC) when defined(uClibc) or defined(linux) or defined(haiku):
# uClibc environment (OpenWrt included) doesn't have the full execvpe
if (poUsePath in data.options): let exe = findExe(data.sysCommand)
when defined(uClibc) or defined(linux): discard execve(exe, data.sysArgs, data.sysEnv)
# uClibc environment (OpenWrt included) doesn't have the full execvpe else:
let exe = findExe(data.sysCommand) # MacOSX doesn't have execvpe, so we need workaround.
discard execve(exe, data.sysArgs, data.sysEnv) # On MacOSX we can arrive here only from fork, so this is safe:
environ = data.sysEnv
discard execvp(data.sysCommand, data.sysArgs)
else: else:
# MacOSX doesn't have execvpe, so we need workaround. discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
# On MacOSX we can arrive here only from fork, so this is safe:
environ = data.sysEnv
discard execvp(data.sysCommand, data.sysArgs)
else:
discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
startProcessFail(data) startProcessFail(data)
{.pop.} {.pop.}
proc close(p: Process) = proc close(p: Process) =
if poParentStreams notin p.options: if poParentStreams notin p.options: