summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2018-06-23 22:22:35 -0700
committerOri Bernstein <ori@eigenstate.org>2018-06-23 22:22:35 -0700
commit974475bcfe52a488d9f5e83e474b6ca3670d5f6a (patch)
tree7932804ae8cf8994c6c66c2cb5dc4897dc94de00
parentf02146462fb1d33442cb0068ae2519588675c9aa (diff)
downloadmc-974475bcfe52a488d9f5e83e474b6ca3670d5f6a.tar.gz
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.
-rw-r--r--lib/std/execvp.myr43
1 files changed, 26 insertions, 17 deletions
diff --git a/lib/std/execvp.myr b/lib/std/execvp.myr
index f6696e3..c24ea47 100644
--- a/lib/std/execvp.myr
+++ b/lib/std/execvp.myr
@@ -4,7 +4,6 @@ use "errno"
use "fmt"
use "option"
use "strfind"
-use "strsplit"
use "syswrap"
pkg std =
@@ -13,46 +12,56 @@ pkg std =
;;
const execvp = {cmd, args
- var paths, binpath
+ var i, j, paths, binpath
var buf : byte[512]
match strfind(cmd, "/")
| `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, "/")
| `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++
+ ;;
+ j = i
+ while j < p.len && p[j] != (':' : byte)
+ j++
;;
- -> strsplit(path, ":")
+ -> (i, j)
}
+