shithub: mc

Download patch

ref: 974475bcfe52a488d9f5e83e474b6ca3670d5f6a
parent: f02146462fb1d33442cb0068ae2519588675c9aa
author: Ori Bernstein <ori@eigenstate.org>
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)
 }
+