mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-09 05:14:20 +00:00
cgen: no type canon for integral types; osproc use posix_spawn instead of fork&exec
This commit is contained in:
@@ -574,7 +574,8 @@ const
|
||||
tyPointer,
|
||||
tyOpenArray, tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128,
|
||||
tyUInt..tyUInt64}
|
||||
|
||||
IntegralTypes* = {tyBool, tyChar, tyEnum, tyInt..tyInt64,
|
||||
tyFloat..tyFloat128, tyUInt..tyUInt64}
|
||||
ConstantDataTypes*: TTypeKinds = {tyArrayConstr, tyArray, tySet,
|
||||
tyTuple, tySequence}
|
||||
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator,
|
||||
|
||||
@@ -265,7 +265,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
|
||||
of tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL")
|
||||
of tyChar: result = typeNameOrLiteral(typ, "NIM_CHAR")
|
||||
of tyNil: result = typeNameOrLiteral(typ, "0")
|
||||
of tyInt..tyFloat128:
|
||||
of tyInt..tyFloat128, tyUInt..tyUInt64:
|
||||
result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.Kind])
|
||||
of tyRange: result = getSimpleTypeDesc(m, typ.sons[0])
|
||||
else: result = nil
|
||||
|
||||
@@ -73,11 +73,15 @@ proc GetUniqueType*(key: PType): PType =
|
||||
if key == nil: return
|
||||
var k = key.kind
|
||||
case k
|
||||
of tyNone, tyBool, tyChar, tyEmpty,
|
||||
tyNil, tyExpr, tyStmt, tyTypeDesc, tyPointer, tyString, tyCString,
|
||||
of tyBool, tyChar,
|
||||
tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
|
||||
tyFloat, tyFloat32, tyFloat64, tyFloat128,
|
||||
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64, tyBigNum:
|
||||
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64:
|
||||
# no canonicalization for integral types, so that e.g. ``pid_t`` is
|
||||
# produced instead of ``NI``.
|
||||
result = key
|
||||
of tyEmpty, tyNil, tyExpr, tyStmt, tyTypeDesc, tyPointer, tyString,
|
||||
tyCString, tyNone, tyBigNum:
|
||||
result = gCanonicalTypes[k]
|
||||
if result == nil:
|
||||
gCanonicalTypes[k] = key
|
||||
|
||||
@@ -427,6 +427,11 @@ __declspec(naked) int __fastcall NimXadd(volatile int* pNum, int val) {
|
||||
#ifdef __GNUC__
|
||||
# define likely(x) __builtin_expect(x, 1)
|
||||
# define unlikely(x) __builtin_expect(x, 0)
|
||||
/* We need the following for the posix wrapper. In particular it will give us
|
||||
POSIX_SPAWN_USEVFORK: */
|
||||
# ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
# endif
|
||||
#else
|
||||
# define likely(x) (x)
|
||||
# define unlikely(x) (x)
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
## the \`identifier\` notation is used.
|
||||
##
|
||||
## This library relies on the header files of your C compiler. The
|
||||
## resulting C code will just include <XYZ.h> and *not* define the
|
||||
## resulting C code will just ``#include <XYZ.h>`` and *not* define the
|
||||
## symbols declared here.
|
||||
|
||||
from times import TTime
|
||||
|
||||
const
|
||||
hasSpawnH = defined(linux)
|
||||
hasSpawnH = true # should exist for every Posix system really nowadays
|
||||
hasAioH = defined(linux)
|
||||
|
||||
when false:
|
||||
@@ -401,9 +401,9 @@ when hasAioH:
|
||||
when hasSpawnH:
|
||||
type
|
||||
Tposix_spawnattr* {.importc: "posix_spawnattr_t",
|
||||
header: "<spawn.h>".} = cint
|
||||
header: "<spawn.h>", final, pure.} = object
|
||||
Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t",
|
||||
header: "<spawn.h>".} = cint
|
||||
header: "<spawn.h>", final, pure.} = object
|
||||
|
||||
type
|
||||
TSocklen* {.importc: "socklen_t", header: "<sys/socket.h>".} = cint
|
||||
@@ -1720,7 +1720,8 @@ when hasSpawnh:
|
||||
POSIX_SPAWN_SETSCHEDULER* {.importc, header: "<spawn.h>".}: cint
|
||||
POSIX_SPAWN_SETSIGDEF* {.importc, header: "<spawn.h>".}: cint
|
||||
POSIX_SPAWN_SETSIGMASK* {.importc, header: "<spawn.h>".}: cint
|
||||
|
||||
POSIX_SPAWN_USEVFORK* {.importc, header: "<spawn.h>".}: cint
|
||||
|
||||
when hasAioH:
|
||||
proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||
proc aio_error*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||
@@ -2369,7 +2370,7 @@ when hasSpawnH:
|
||||
importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_setsigdefault*(a1: var tposix_spawnattr,
|
||||
a2: var tsigset): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_setflags*(a1: var tposix_spawnattr, a2: cshort): cint {.
|
||||
proc posix_spawnattr_setflags*(a1: var tposix_spawnattr, a2: cint): cint {.
|
||||
importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_setpgroup*(a1: var tposix_spawnattr, a2: tpid): cint {.
|
||||
importc, header: "<spawn.h>".}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
discard """
|
||||
cmd: "nimrod cc --hints:on --threads:on $# $#"
|
||||
"""
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
|
||||
@@ -25,9 +25,10 @@ type
|
||||
when defined(windows):
|
||||
FProcessHandle: Thandle
|
||||
inputHandle, outputHandle, errorHandle: TFileHandle
|
||||
id: THandle
|
||||
else:
|
||||
inputHandle, outputHandle, errorHandle: TFileHandle
|
||||
id: cint
|
||||
id: TPid
|
||||
exitCode: cint
|
||||
|
||||
PProcess* = ref TProcess ## represents an operating system process
|
||||
@@ -158,6 +159,10 @@ proc execProcesses*(cmds: openArray[string],
|
||||
## executes the commands `cmds` in parallel. Creates `n` processes
|
||||
## that execute in parallel. The highest return value of all processes
|
||||
## is returned.
|
||||
when defined(posix):
|
||||
# poParentStreams causes problems on Posix, so we disable it simply:
|
||||
var options = options - {poParentStreams}
|
||||
|
||||
assert n > 0
|
||||
if n > 1:
|
||||
var q: seq[PProcess]
|
||||
@@ -475,6 +480,17 @@ elif not defined(useNimRtl):
|
||||
copyMem(result[i], addr(x[0]), x.len+1)
|
||||
inc(i)
|
||||
|
||||
proc EnvToCStringArray(): cstringArray =
|
||||
var counter = 0
|
||||
for key, val in envPairs(): inc counter
|
||||
result = cast[cstringArray](alloc0((counter + 1) * sizeof(cstring)))
|
||||
var i = 0
|
||||
for key, val in envPairs():
|
||||
var x = key & "=" & val
|
||||
result[i] = cast[cstring](alloc(x.len+1))
|
||||
copyMem(result[i], addr(x[0]), x.len+1)
|
||||
inc(i)
|
||||
|
||||
proc startProcess(command: string,
|
||||
workingDir: string = "",
|
||||
args: openarray[string] = [],
|
||||
@@ -484,58 +500,122 @@ elif not defined(useNimRtl):
|
||||
p_stdin, p_stdout, p_stderr: array [0..1, cint]
|
||||
new(result)
|
||||
result.exitCode = -3 # for ``waitForExit``
|
||||
if pipe(p_stdin) != 0'i32 or pipe(p_stdout) != 0'i32 or
|
||||
pipe(p_stderr) != 0'i32:
|
||||
OSError()
|
||||
var Pid = fork()
|
||||
if Pid < 0: OSError()
|
||||
if poParentStreams notin options:
|
||||
if pipe(p_stdin) != 0'i32 or pipe(p_stdout) != 0'i32 or
|
||||
pipe(p_stderr) != 0'i32:
|
||||
OSError()
|
||||
|
||||
var pid: TPid
|
||||
when defined(posix_spawn) and not defined(useFork):
|
||||
var attr: Tposix_spawnattr
|
||||
var fops: Tposix_spawn_file_actions
|
||||
|
||||
if pid == 0:
|
||||
## child process:
|
||||
discard close(p_stdin[writeIdx])
|
||||
if dup2(p_stdin[readIdx], readIdx) < 0: OSError()
|
||||
discard close(p_stdout[readIdx])
|
||||
if dup2(p_stdout[writeIdx], writeIdx) < 0: OSError()
|
||||
discard close(p_stderr[readIdx])
|
||||
if poStdErrToStdOut in options:
|
||||
if dup2(p_stdout[writeIdx], 2) < 0: OSError()
|
||||
else:
|
||||
if dup2(p_stderr[writeIdx], 2) < 0: OSError()
|
||||
template chck(e: expr) =
|
||||
if e != 0'i32: OSError()
|
||||
|
||||
# Create a new process group
|
||||
if setpgid(0, 0) == -1: quit("setpgid call failed: " & $strerror(errno))
|
||||
chck posix_spawn_file_actions_init(fops)
|
||||
chck posix_spawnattr_init(attr)
|
||||
|
||||
var mask: Tsigset
|
||||
chck sigemptyset(mask)
|
||||
chck posix_spawnattr_setsigmask(attr, mask)
|
||||
chck posix_spawnattr_setpgroup(attr, 0'i32)
|
||||
|
||||
chck posix_spawnattr_setflags(attr, POSIX_SPAWN_USEVFORK or
|
||||
POSIX_SPAWN_SETSIGMASK or
|
||||
POSIX_SPAWN_SETPGROUP)
|
||||
|
||||
if poParentStreams notin options:
|
||||
chck posix_spawn_file_actions_addclose(fops, p_stdin[writeIdx])
|
||||
chck posix_spawn_file_actions_adddup2(fops, p_stdin[readIdx], readIdx)
|
||||
chck posix_spawn_file_actions_addclose(fops, p_stdout[readIdx])
|
||||
chck posix_spawn_file_actions_adddup2(fops, p_stdout[writeIdx], writeIdx)
|
||||
chck posix_spawn_file_actions_addclose(fops, p_stderr[readIdx])
|
||||
if poStdErrToStdOut in options:
|
||||
chck posix_spawn_file_actions_adddup2(fops, p_stdout[writeIdx], 2)
|
||||
else:
|
||||
chck posix_spawn_file_actions_adddup2(fops, p_stderr[writeIdx], 2)
|
||||
|
||||
var e = if env == nil: EnvToCStringArray() else: ToCStringArray(env)
|
||||
|
||||
if workingDir.len > 0: os.setCurrentDir(workingDir)
|
||||
if poUseShell notin options:
|
||||
var a = toCStringArray([extractFilename(command)], args)
|
||||
if env == nil:
|
||||
discard execv(command, a)
|
||||
else:
|
||||
discard execve(command, a, ToCStringArray(env))
|
||||
chck posix_spawn(pid, command, fops, attr, a, e)
|
||||
else:
|
||||
var x = addCmdArgs(command, args)
|
||||
var a = toCStringArray(["sh", "-c"], [x])
|
||||
if env == nil:
|
||||
discard execv("/bin/sh", a)
|
||||
chck posix_spawn(pid, "/bin/sh", fops, attr, a, e)
|
||||
|
||||
if {poEchoCmd, poUseShell} * options == {poEchoCmd}:
|
||||
# shell echos already, so ...
|
||||
echo(command, " ", join(args, " "))
|
||||
|
||||
chck posix_spawn_file_actions_destroy(fops)
|
||||
chck posix_spawnattr_destroy(attr)
|
||||
|
||||
else:
|
||||
|
||||
Pid = fork()
|
||||
if Pid < 0: OSError()
|
||||
if pid == 0:
|
||||
## child process:
|
||||
|
||||
if poParentStreams notin options:
|
||||
discard close(p_stdin[writeIdx])
|
||||
if dup2(p_stdin[readIdx], readIdx) < 0: OSError()
|
||||
discard close(p_stdout[readIdx])
|
||||
if dup2(p_stdout[writeIdx], writeIdx) < 0: OSError()
|
||||
discard close(p_stderr[readIdx])
|
||||
if poStdErrToStdOut in options:
|
||||
if dup2(p_stdout[writeIdx], 2) < 0: OSError()
|
||||
else:
|
||||
if dup2(p_stderr[writeIdx], 2) < 0: OSError()
|
||||
|
||||
# Create a new process group
|
||||
if setpgid(0, 0) == -1: quit("setpgid call failed: " & $strerror(errno))
|
||||
|
||||
if workingDir.len > 0: os.setCurrentDir(workingDir)
|
||||
if poUseShell notin options:
|
||||
var a = toCStringArray([extractFilename(command)], args)
|
||||
if env == nil:
|
||||
discard execv(command, a)
|
||||
else:
|
||||
discard execve(command, a, ToCStringArray(env))
|
||||
else:
|
||||
discard execve("/bin/sh", a, ToCStringArray(env))
|
||||
# too risky to raise an exception here:
|
||||
quit("execve call failed: " & $strerror(errno))
|
||||
var x = addCmdArgs(command, args)
|
||||
var a = toCStringArray(["sh", "-c"], [x])
|
||||
if env == nil:
|
||||
discard execv("/bin/sh", a)
|
||||
else:
|
||||
discard execve("/bin/sh", a, ToCStringArray(env))
|
||||
# too risky to raise an exception here:
|
||||
quit("execve call failed: " & $strerror(errno))
|
||||
# Parent process. Copy process information.
|
||||
if poEchoCmd in options:
|
||||
# shell with no redirects echos already, so ...
|
||||
echo(command, " ", join(args, " "))
|
||||
result.id = pid
|
||||
|
||||
result.inputHandle = p_stdin[writeIdx]
|
||||
result.outputHandle = p_stdout[readIdx]
|
||||
if poStdErrToStdOut in options:
|
||||
result.errorHandle = result.outputHandle
|
||||
discard close(p_stderr[readIdx])
|
||||
if poParentStreams in options:
|
||||
# does not make much sense, but better than nothing:
|
||||
result.inputHandle = 0
|
||||
result.outputHandle = 1
|
||||
if poStdErrToStdOut in options:
|
||||
result.errorHandle = result.outputHandle
|
||||
else:
|
||||
result.errorHandle = 2
|
||||
else:
|
||||
result.errorHandle = p_stderr[readIdx]
|
||||
discard close(p_stderr[writeIdx])
|
||||
discard close(p_stdin[readIdx])
|
||||
discard close(p_stdout[writeIdx])
|
||||
result.inputHandle = p_stdin[writeIdx]
|
||||
result.outputHandle = p_stdout[readIdx]
|
||||
if poStdErrToStdOut in options:
|
||||
result.errorHandle = result.outputHandle
|
||||
discard close(p_stderr[readIdx])
|
||||
else:
|
||||
result.errorHandle = p_stderr[readIdx]
|
||||
discard close(p_stderr[writeIdx])
|
||||
discard close(p_stdin[readIdx])
|
||||
discard close(p_stdout[writeIdx])
|
||||
|
||||
proc close(p: PProcess) =
|
||||
discard close(p.inputHandle)
|
||||
|
||||
@@ -27,7 +27,8 @@ type
|
||||
|
||||
when defined(posix):
|
||||
type
|
||||
TTime* = distinct int ## distinct type that represents a time
|
||||
TTimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int
|
||||
TTime* = distinct TTimeImpl ## distinct type that represents a time
|
||||
|
||||
Ttimeval {.importc: "struct timeval", header: "<sys/select.h>",
|
||||
final, pure.} = object ## struct timeval
|
||||
@@ -46,9 +47,12 @@ elif defined(windows):
|
||||
|
||||
when defined(vcc):
|
||||
# newest version of Visual C++ defines time_t to be of 64 bits
|
||||
type TTime* = distinct int64
|
||||
type TTimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int64
|
||||
else:
|
||||
type TTime* = distinct int32
|
||||
type TTimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int32
|
||||
|
||||
type
|
||||
TTime* = distinct TTimeImpl
|
||||
|
||||
elif defined(ECMAScript):
|
||||
type
|
||||
|
||||
@@ -117,6 +117,9 @@ Library Additions
|
||||
- Added ``ftpclient`` module.
|
||||
- Added ``memfiles`` module.
|
||||
- Added ``osproc.startCmd``, ``osproc.execCmdEx``.
|
||||
- The ``osproc`` module now uses ``posix_spawn`` instead of ``fork``
|
||||
and ``exec`` on Posix systems. Define the symbol ``useFork`` to revert to
|
||||
the old implementation.
|
||||
|
||||
|
||||
2011-07-10 Version 0.8.12 released
|
||||
|
||||
Reference in New Issue
Block a user