cgen: no type canon for integral types; osproc use posix_spawn instead of fork&exec
This commit is contained in:
parent
b05418a431
commit
61792dc7d6
9 changed files with 149 additions and 54 deletions
|
|
@ -574,7 +574,8 @@ const
|
||||||
tyPointer,
|
tyPointer,
|
||||||
tyOpenArray, tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128,
|
tyOpenArray, tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128,
|
||||||
tyUInt..tyUInt64}
|
tyUInt..tyUInt64}
|
||||||
|
IntegralTypes* = {tyBool, tyChar, tyEnum, tyInt..tyInt64,
|
||||||
|
tyFloat..tyFloat128, tyUInt..tyUInt64}
|
||||||
ConstantDataTypes*: TTypeKinds = {tyArrayConstr, tyArray, tySet,
|
ConstantDataTypes*: TTypeKinds = {tyArrayConstr, tyArray, tySet,
|
||||||
tyTuple, tySequence}
|
tyTuple, tySequence}
|
||||||
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator,
|
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 tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL")
|
||||||
of tyChar: result = typeNameOrLiteral(typ, "NIM_CHAR")
|
of tyChar: result = typeNameOrLiteral(typ, "NIM_CHAR")
|
||||||
of tyNil: result = typeNameOrLiteral(typ, "0")
|
of tyNil: result = typeNameOrLiteral(typ, "0")
|
||||||
of tyInt..tyFloat128:
|
of tyInt..tyFloat128, tyUInt..tyUInt64:
|
||||||
result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.Kind])
|
result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.Kind])
|
||||||
of tyRange: result = getSimpleTypeDesc(m, typ.sons[0])
|
of tyRange: result = getSimpleTypeDesc(m, typ.sons[0])
|
||||||
else: result = nil
|
else: result = nil
|
||||||
|
|
|
||||||
|
|
@ -73,11 +73,15 @@ proc GetUniqueType*(key: PType): PType =
|
||||||
if key == nil: return
|
if key == nil: return
|
||||||
var k = key.kind
|
var k = key.kind
|
||||||
case k
|
case k
|
||||||
of tyNone, tyBool, tyChar, tyEmpty,
|
of tyBool, tyChar,
|
||||||
tyNil, tyExpr, tyStmt, tyTypeDesc, tyPointer, tyString, tyCString,
|
|
||||||
tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
|
tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
|
||||||
tyFloat, tyFloat32, tyFloat64, tyFloat128,
|
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]
|
result = gCanonicalTypes[k]
|
||||||
if result == nil:
|
if result == nil:
|
||||||
gCanonicalTypes[k] = key
|
gCanonicalTypes[k] = key
|
||||||
|
|
|
||||||
|
|
@ -427,6 +427,11 @@ __declspec(naked) int __fastcall NimXadd(volatile int* pNum, int val) {
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# define likely(x) __builtin_expect(x, 1)
|
# define likely(x) __builtin_expect(x, 1)
|
||||||
# define unlikely(x) __builtin_expect(x, 0)
|
# 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
|
#else
|
||||||
# define likely(x) (x)
|
# define likely(x) (x)
|
||||||
# define unlikely(x) (x)
|
# define unlikely(x) (x)
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,13 @@
|
||||||
## the \`identifier\` notation is used.
|
## the \`identifier\` notation is used.
|
||||||
##
|
##
|
||||||
## This library relies on the header files of your C compiler. The
|
## 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.
|
## symbols declared here.
|
||||||
|
|
||||||
from times import TTime
|
from times import TTime
|
||||||
|
|
||||||
const
|
const
|
||||||
hasSpawnH = defined(linux)
|
hasSpawnH = true # should exist for every Posix system really nowadays
|
||||||
hasAioH = defined(linux)
|
hasAioH = defined(linux)
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
|
|
@ -401,9 +401,9 @@ when hasAioH:
|
||||||
when hasSpawnH:
|
when hasSpawnH:
|
||||||
type
|
type
|
||||||
Tposix_spawnattr* {.importc: "posix_spawnattr_t",
|
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",
|
Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t",
|
||||||
header: "<spawn.h>".} = cint
|
header: "<spawn.h>", final, pure.} = object
|
||||||
|
|
||||||
type
|
type
|
||||||
TSocklen* {.importc: "socklen_t", header: "<sys/socket.h>".} = cint
|
TSocklen* {.importc: "socklen_t", header: "<sys/socket.h>".} = cint
|
||||||
|
|
@ -1720,6 +1720,7 @@ when hasSpawnh:
|
||||||
POSIX_SPAWN_SETSCHEDULER* {.importc, header: "<spawn.h>".}: cint
|
POSIX_SPAWN_SETSCHEDULER* {.importc, header: "<spawn.h>".}: cint
|
||||||
POSIX_SPAWN_SETSIGDEF* {.importc, header: "<spawn.h>".}: cint
|
POSIX_SPAWN_SETSIGDEF* {.importc, header: "<spawn.h>".}: cint
|
||||||
POSIX_SPAWN_SETSIGMASK* {.importc, header: "<spawn.h>".}: cint
|
POSIX_SPAWN_SETSIGMASK* {.importc, header: "<spawn.h>".}: cint
|
||||||
|
POSIX_SPAWN_USEVFORK* {.importc, header: "<spawn.h>".}: cint
|
||||||
|
|
||||||
when hasAioH:
|
when hasAioH:
|
||||||
proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||||
|
|
@ -2369,7 +2370,7 @@ when hasSpawnH:
|
||||||
importc, header: "<spawn.h>".}
|
importc, header: "<spawn.h>".}
|
||||||
proc posix_spawnattr_setsigdefault*(a1: var tposix_spawnattr,
|
proc posix_spawnattr_setsigdefault*(a1: var tposix_spawnattr,
|
||||||
a2: var tsigset): cint {.importc, header: "<spawn.h>".}
|
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>".}
|
importc, header: "<spawn.h>".}
|
||||||
proc posix_spawnattr_setpgroup*(a1: var tposix_spawnattr, a2: tpid): cint {.
|
proc posix_spawnattr_setpgroup*(a1: var tposix_spawnattr, a2: tpid): cint {.
|
||||||
importc, header: "<spawn.h>".}
|
importc, header: "<spawn.h>".}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
discard """
|
|
||||||
cmd: "nimrod cc --hints:on --threads:on $# $#"
|
|
||||||
"""
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,10 @@ type
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
FProcessHandle: Thandle
|
FProcessHandle: Thandle
|
||||||
inputHandle, outputHandle, errorHandle: TFileHandle
|
inputHandle, outputHandle, errorHandle: TFileHandle
|
||||||
|
id: THandle
|
||||||
else:
|
else:
|
||||||
inputHandle, outputHandle, errorHandle: TFileHandle
|
inputHandle, outputHandle, errorHandle: TFileHandle
|
||||||
id: cint
|
id: TPid
|
||||||
exitCode: cint
|
exitCode: cint
|
||||||
|
|
||||||
PProcess* = ref TProcess ## represents an operating system process
|
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
|
## executes the commands `cmds` in parallel. Creates `n` processes
|
||||||
## that execute in parallel. The highest return value of all processes
|
## that execute in parallel. The highest return value of all processes
|
||||||
## is returned.
|
## is returned.
|
||||||
|
when defined(posix):
|
||||||
|
# poParentStreams causes problems on Posix, so we disable it simply:
|
||||||
|
var options = options - {poParentStreams}
|
||||||
|
|
||||||
assert n > 0
|
assert n > 0
|
||||||
if n > 1:
|
if n > 1:
|
||||||
var q: seq[PProcess]
|
var q: seq[PProcess]
|
||||||
|
|
@ -475,6 +480,17 @@ elif not defined(useNimRtl):
|
||||||
copyMem(result[i], addr(x[0]), x.len+1)
|
copyMem(result[i], addr(x[0]), x.len+1)
|
||||||
inc(i)
|
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,
|
proc startProcess(command: string,
|
||||||
workingDir: string = "",
|
workingDir: string = "",
|
||||||
args: openarray[string] = [],
|
args: openarray[string] = [],
|
||||||
|
|
@ -484,58 +500,122 @@ elif not defined(useNimRtl):
|
||||||
p_stdin, p_stdout, p_stderr: array [0..1, cint]
|
p_stdin, p_stdout, p_stderr: array [0..1, cint]
|
||||||
new(result)
|
new(result)
|
||||||
result.exitCode = -3 # for ``waitForExit``
|
result.exitCode = -3 # for ``waitForExit``
|
||||||
if pipe(p_stdin) != 0'i32 or pipe(p_stdout) != 0'i32 or
|
if poParentStreams notin options:
|
||||||
pipe(p_stderr) != 0'i32:
|
if pipe(p_stdin) != 0'i32 or pipe(p_stdout) != 0'i32 or
|
||||||
OSError()
|
pipe(p_stderr) != 0'i32:
|
||||||
var Pid = fork()
|
OSError()
|
||||||
if Pid < 0: OSError()
|
|
||||||
|
|
||||||
if pid == 0:
|
var pid: TPid
|
||||||
## child process:
|
when defined(posix_spawn) and not defined(useFork):
|
||||||
discard close(p_stdin[writeIdx])
|
var attr: Tposix_spawnattr
|
||||||
if dup2(p_stdin[readIdx], readIdx) < 0: OSError()
|
var fops: Tposix_spawn_file_actions
|
||||||
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
|
template chck(e: expr) =
|
||||||
if setpgid(0, 0) == -1: quit("setpgid call failed: " & $strerror(errno))
|
if e != 0'i32: OSError()
|
||||||
|
|
||||||
|
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 workingDir.len > 0: os.setCurrentDir(workingDir)
|
||||||
if poUseShell notin options:
|
if poUseShell notin options:
|
||||||
var a = toCStringArray([extractFilename(command)], args)
|
var a = toCStringArray([extractFilename(command)], args)
|
||||||
if env == nil:
|
chck posix_spawn(pid, command, fops, attr, a, e)
|
||||||
discard execv(command, a)
|
|
||||||
else:
|
|
||||||
discard execve(command, a, ToCStringArray(env))
|
|
||||||
else:
|
else:
|
||||||
var x = addCmdArgs(command, args)
|
var x = addCmdArgs(command, args)
|
||||||
var a = toCStringArray(["sh", "-c"], [x])
|
var a = toCStringArray(["sh", "-c"], [x])
|
||||||
if env == nil:
|
chck posix_spawn(pid, "/bin/sh", fops, attr, a, e)
|
||||||
discard execv("/bin/sh", a)
|
|
||||||
|
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:
|
else:
|
||||||
discard execve("/bin/sh", a, ToCStringArray(env))
|
var x = addCmdArgs(command, args)
|
||||||
# too risky to raise an exception here:
|
var a = toCStringArray(["sh", "-c"], [x])
|
||||||
quit("execve call failed: " & $strerror(errno))
|
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.
|
# Parent process. Copy process information.
|
||||||
if poEchoCmd in options:
|
if poEchoCmd in options:
|
||||||
|
# shell with no redirects echos already, so ...
|
||||||
echo(command, " ", join(args, " "))
|
echo(command, " ", join(args, " "))
|
||||||
result.id = pid
|
result.id = pid
|
||||||
|
|
||||||
result.inputHandle = p_stdin[writeIdx]
|
if poParentStreams in options:
|
||||||
result.outputHandle = p_stdout[readIdx]
|
# does not make much sense, but better than nothing:
|
||||||
if poStdErrToStdOut in options:
|
result.inputHandle = 0
|
||||||
result.errorHandle = result.outputHandle
|
result.outputHandle = 1
|
||||||
discard close(p_stderr[readIdx])
|
if poStdErrToStdOut in options:
|
||||||
|
result.errorHandle = result.outputHandle
|
||||||
|
else:
|
||||||
|
result.errorHandle = 2
|
||||||
else:
|
else:
|
||||||
result.errorHandle = p_stderr[readIdx]
|
result.inputHandle = p_stdin[writeIdx]
|
||||||
discard close(p_stderr[writeIdx])
|
result.outputHandle = p_stdout[readIdx]
|
||||||
discard close(p_stdin[readIdx])
|
if poStdErrToStdOut in options:
|
||||||
discard close(p_stdout[writeIdx])
|
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) =
|
proc close(p: PProcess) =
|
||||||
discard close(p.inputHandle)
|
discard close(p.inputHandle)
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@ type
|
||||||
|
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
type
|
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>",
|
Ttimeval {.importc: "struct timeval", header: "<sys/select.h>",
|
||||||
final, pure.} = object ## struct timeval
|
final, pure.} = object ## struct timeval
|
||||||
|
|
@ -46,9 +47,12 @@ elif defined(windows):
|
||||||
|
|
||||||
when defined(vcc):
|
when defined(vcc):
|
||||||
# newest version of Visual C++ defines time_t to be of 64 bits
|
# 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:
|
else:
|
||||||
type TTime* = distinct int32
|
type TTimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int32
|
||||||
|
|
||||||
|
type
|
||||||
|
TTime* = distinct TTimeImpl
|
||||||
|
|
||||||
elif defined(ECMAScript):
|
elif defined(ECMAScript):
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,9 @@ Library Additions
|
||||||
- Added ``ftpclient`` module.
|
- Added ``ftpclient`` module.
|
||||||
- Added ``memfiles`` module.
|
- Added ``memfiles`` module.
|
||||||
- Added ``osproc.startCmd``, ``osproc.execCmdEx``.
|
- 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
|
2011-07-10 Version 0.8.12 released
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue