summary refs log tree commit diff stats
path: root/lib/pure/osproc.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/osproc.nim')
-rw-r--r--lib/pure/osproc.nim20
1 files changed, 15 insertions, 5 deletions
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 5d6848565..6e250f9d5 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -137,6 +137,14 @@ proc startProcess*(command: string,
   ## to `startProcess`. See the documentation of ``TProcessOption`` for the
   ## meaning of these flags. You need to `close` the process when done.
   ##
+  ## Note that you can't pass any `args` if you use the option
+  ## ``poEvalCommand``, which invokes the system shell to run the specified
+  ## `command`. In this situation you have to concatenate manually the contents
+  ## of `args` to `command` carefully escaping/quoting any special characters,
+  ## since it will be passed *as is* to the system shell. Each system/shell may
+  ## feature different escaping rules, so try to avoid this kind of shell
+  ## invokation if possible as it leads to non portable software.
+  ##
   ## Return value: The newly created process object. Nil is never returned,
   ## but ``EOS`` is raised in case of an error.
 
@@ -607,11 +615,13 @@ elif not defined(useNimRtl):
     optionPoStdErrToStdOut: bool
 
   when not defined(useFork):
-    proc startProcessAuxSpawn(data: TStartProcessData): TPid {.tags: [FExecIO, FReadEnv].}
-  proc startProcessAuxFork(data: TStartProcessData): TPid {.tags: [FExecIO, FReadEnv].}
+    proc startProcessAuxSpawn(data: TStartProcessData): TPid {.
+      tags: [FExecIO, FReadEnv], gcsafe.}
+  proc startProcessAuxFork(data: TStartProcessData): TPid {.
+    tags: [FExecIO, FReadEnv], gcsafe.}
   {.push stacktrace: off, profiler: off.}
   proc startProcessAfterFork(data: ptr TStartProcessData) {.
-    tags: [FExecIO, FReadEnv], cdecl.}
+    tags: [FExecIO, FReadEnv], cdecl, gcsafe.}
   {.pop.}
 
   proc startProcess(command: string,
@@ -633,7 +643,7 @@ elif not defined(useNimRtl):
     if poEvalCommand in options:
       sysCommand = "/bin/sh"
       sysArgsRaw = @[sysCommand, "-c", command]
-      assert args.len == 0
+      assert args.len == 0, "`args` has to be empty when using poEvalCommand."
     else:
       sysCommand = command
       sysArgsRaw = @[command]
@@ -938,7 +948,7 @@ elif not defined(useNimRtl):
 proc execCmdEx*(command: string, options: set[TProcessOption] = {
                 poStdErrToStdOut, poUsePath}): tuple[
                 output: TaintedString,
-                exitCode: int] {.tags: [FExecIO, FReadIO].} =
+                exitCode: int] {.tags: [FExecIO, FReadIO], gcsafe.} =
   ## a convenience proc that runs the `command`, grabs all its output and
   ## exit code and returns both.
   var p = startCmd(command, options)