cgen: no type canon for integral types; osproc use posix_spawn instead of fork&exec

This commit is contained in:
Araq 2011-11-18 00:29:56 +01:00
commit 61792dc7d6
9 changed files with 149 additions and 54 deletions

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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,7 +1720,8 @@ 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>".}
proc aio_error*(a1: 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>".} 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>".}

View file

@ -1,6 +1,3 @@
discard """
cmd: "nimrod cc --hints:on --threads:on $# $#"
"""
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library

View file

@ -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()
var pid: TPid
when defined(posix_spawn) and not defined(useFork):
var attr: Tposix_spawnattr
var fops: Tposix_spawn_file_actions
if pid == 0: template chck(e: expr) =
## child process: if e != 0'i32: OSError()
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 chck posix_spawn_file_actions_init(fops)
if setpgid(0, 0) == -1: quit("setpgid call failed: " & $strerror(errno)) 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)

View file

@ -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

View file

@ -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