diff options
author | Araq <rumpf_a@web.de> | 2011-11-18 00:29:56 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-11-18 00:29:56 +0100 |
commit | 61792dc7d6926bcaeed858f9acc00ec7e1517724 (patch) | |
tree | ac03827c7dd33e5395652b3da02844e6d973e687 /lib | |
parent | b05418a4310c5e9fb9074a66bccba13a95053616 (diff) | |
download | Nim-61792dc7d6926bcaeed858f9acc00ec7e1517724.tar.gz |
cgen: no type canon for integral types; osproc use posix_spawn instead of fork&exec
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/nimbase.h | 5 | ||||
-rwxr-xr-x | lib/posix/posix.nim | 13 | ||||
-rw-r--r-- | lib/pure/actors.nim | 3 | ||||
-rwxr-xr-x | lib/pure/osproc.nim | 160 | ||||
-rwxr-xr-x | lib/pure/times.nim | 10 |
5 files changed, 139 insertions, 52 deletions
diff --git a/lib/nimbase.h b/lib/nimbase.h index 11278ccd2..d42befea7 100755 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -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) diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index 966093c81..c1cf819b7 100755 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -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>".} diff --git a/lib/pure/actors.nim b/lib/pure/actors.nim index 091abc050..4576cb602 100644 --- a/lib/pure/actors.nim +++ b/lib/pure/actors.nim @@ -1,6 +1,3 @@ -discard """ - cmd: "nimrod cc --hints:on --threads:on $# $#" -""" # # # Nimrod's Runtime Library diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 608fce013..ca4483c8b 100755 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -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 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() - - # Create a new process group - if setpgid(0, 0) == -1: quit("setpgid call failed: " & $strerror(errno)) - + 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 + + template chck(e: expr) = + 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 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) diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 378d6ae80..8c5db1735 100755 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -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 |