diff options
author | Ori Bernstein <ori@eigenstate.org> | 2018-06-23 22:22:35 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2018-06-23 22:22:35 -0700 |
commit | 974475bcfe52a488d9f5e83e474b6ca3670d5f6a (patch) | |
tree | 7932804ae8cf8994c6c66c2cb5dc4897dc94de00 /lib/std/execvp.myr | |
parent | f02146462fb1d33442cb0068ae2519588675c9aa (diff) | |
download | mc-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.
Diffstat (limited to 'lib/std/execvp.myr')
-rw-r--r-- | lib/std/execvp.myr | 43 |
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) } + |