ref: 974475bcfe52a488d9f5e83e474b6ca3670d5f6a
parent: f02146462fb1d33442cb0068ae2519588675c9aa
author: Ori Bernstein <[email protected]>
date: Sat Jun 23 18:22:35 EDT 2018
Make execvp work with zero allocations. This fixes a bug when exec'ing from forked process in a program that uses threads. The allocator from another thread can be holding the lock at fork, so when we fork it's possible that there's nobody left to unlock, and we deeadlock.
--- a/lib/std/execvp.myr
+++ b/lib/std/execvp.myr
@@ -4,7 +4,6 @@
use "fmt"
use "option"
use "strfind"
-use "strsplit"
use "syswrap"
pkg std =
@@ -13,7 +12,7 @@
;;
const execvp = {cmd, args
- var paths, binpath
+ var i, j, paths, binpath
var buf : byte[512]
match strfind(cmd, "/")
@@ -20,18 +19,20 @@
| `Some _:
-> execv(cmd, args)
| `None:
- paths = getpaths()
- for p : paths
- binpath = bfmt(buf[:], "{}/{}", p, cmd)
+ i = 0
+ j = 0
+ paths = std.getenvv("PATH", "/usr/local/bin:/bin:/usr/bin")
+ while j < paths.len
+ (i, j) = nextpath(paths, j)
+ binpath = bfmt(buf[:], "{}/{}", paths[i:j], cmd)
execv(binpath, args)
;;
- slfree(paths)
;;
-> -1
}
const execvpe = {cmd, args, env
- var paths, binpath
+ var i, j, paths, binpath
var buf : byte[512]
match strfind(cmd, "/")
@@ -38,21 +39,29 @@
| `Some _:
-> execve(cmd, args, env)
| `None:
- paths = getpaths()
- for p : paths
- binpath = bfmt(buf[:], "{}/{}", p, cmd)
+ i = 0
+ j = 0
+ paths = std.getenvv("PATH", "/usr/local/bin:/bin:/usr/bin")
+ while j < paths.len
+ (i, j) = nextpath(paths, j)
+ binpath = bfmt(buf[:], "{}/{}", paths[i:j], cmd)
execve(binpath, args, env)
;;
- slfree(paths)
;;
-> -1
}
-const getpaths = {
- var path
- match getenv("PATH")
- | `Some p: path = p
- | `None: path = "/usr/local/bin:/bin:/usr/bin"
+const nextpath = {p, start
+ var i, j
+
+ i = start
+ while i < p.len && p[i] == (':' : byte)
+ i++
;;
- -> strsplit(path, ":")
+ j = i
+ while j < p.len && p[j] != (':' : byte)
+ j++
+ ;;
+ -> (i, j)
}
+