summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@markovcorp.com>2018-02-15 11:19:03 -0800
committerOri Bernstein <ori@markovcorp.com>2018-02-15 11:19:03 -0800
commit9cb3a0f22ac95f75e87e944b95b6c5a13a4eb729 (patch)
tree282316079fa9f4f5f5d1864fb0747c08f3400fc8
parentf8b121ae9b3e57bbca8304676d417f680ad26f7a (diff)
downloadmc-9cb3a0f22ac95f75e87e944b95b6c5a13a4eb729.tar.gz
Be a bit better about cleaning up fds on error.
-rw-r--r--lib/std/spork.myr59
-rw-r--r--support/syscall-gen/specials+linux-x64.frag4
2 files changed, 47 insertions, 16 deletions
diff --git a/lib/std/spork.myr b/lib/std/spork.myr
index 392ecc6..0a02a64 100644
--- a/lib/std/spork.myr
+++ b/lib/std/spork.myr
@@ -33,14 +33,17 @@ const spork = {cmd
var infds : fd[2], outfds : fd[2]
var err
+ /* init for safe close */
+ infds = [-1, -1]
+ outfds = [-1, -1]
/* open up pipes */
err = pipe(&infds)
if err != Enone
- -> `Err err
+ goto sporkerr
;;
err = pipe(&outfds)
if err != Enone
- -> `Err err
+ goto sporkerr
;;
match sporkfd(cmd, infds, outfds, [-1, 2])
@@ -50,26 +53,37 @@ const spork = {cmd
close(outfds[1]);
-> `Ok (pid, infds[1], outfds[0])
| `Err m:
- -> `Err m
+ err = m
+ goto sporkerr
;;
+:sporkerr
+ close(infds[0])
+ close(infds[1])
+ close(outfds[0])
+ close(outfds[1])
+ -> `Err err
}
const espork = {cmd
var infds : fd[2], outfds : fd[2], errfds : fd[2]
var err
+ /* init for safe close */
+ infds = [-1, -1]
+ outfds = [-1, -1]
+ errfds = [-1, -1]
/* open up pipes */
err = pipe(&infds)
if err != Enone
- -> `Err err
+ goto sporkerr
;;
err = pipe(&outfds)
if err != Enone
- -> `Err err
+ goto sporkerr
;;
err = pipe(&errfds)
if err != Enone
- -> `Err err
+ goto sporkerr
;;
match sporkfd(cmd, infds, outfds, errfds)
@@ -80,8 +94,18 @@ const espork = {cmd
close(errfds[1]);
-> `Ok (pid, infds[1], outfds[0], errfds[0])
| `Err m:
- -> `Err m
+ err = m
+ goto sporkerr
;;
+:sporkerr
+ /* close on a bad fd is ok. */
+ close(infds[0])
+ close(infds[1])
+ close(outfds[0])
+ close(outfds[1])
+ close(errfds[0])
+ close(errfds[1])
+ -> `Err err
}
const filterfd = {fd, cmd
@@ -110,13 +134,20 @@ const sporkfd = {cmd, infds, outfds, errfds
pid = fork()
/* error */
if pid < 0
- /* we don't want to leak the pipe fds on error */
- close(infds[0]);
- close(infds[1]);
- close(outfds[0]);
- close(outfds[1]);
- close(errfds[0]);
- close(errfds[1]);
+ /*
+ so we don't leak fds on error,
+ close the child's ends. The parent
+ handles closing its fds.
+ */
+ if infds[1] != 0
+ close(infds[1]);
+ ;;
+ if outfds[0] != 1
+ close(outfds[0]);
+ ;;
+ if errfds[0] != 2
+ close(errfds[0]);
+ ;;
-> `Err (pid : errno)
/* child */
elif pid == 0
diff --git a/support/syscall-gen/specials+linux-x64.frag b/support/syscall-gen/specials+linux-x64.frag
index d279af7..de2ce27 100644
--- a/support/syscall-gen/specials+linux-x64.frag
+++ b/support/syscall-gen/specials+linux-x64.frag
@@ -19,7 +19,7 @@ extern const fnclone : ( flags : cloneopt, \
fn : void# /* we need a raw pointer */ \
-> pid)
const wait4 : (pid:pid, loc:int32#, opt : int64, usage:rusage# -> int64)
-const waitpid : (pid:pid, loc:int32#, opt : int64 -> int64)
+const waitpid : (pid:pid, loc:int32#, opt : int64 -> pid)
const execv : (cmd : byte[:], args : byte[:][:] -> int64)
const execve : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
/* wrappers to extract wait status */
@@ -119,7 +119,7 @@ const clone = {flags, stk, ptid, ctid, ptreg; -> (syscall(Sysclone, a(flags), a(
const wait4 = {pid, loc, opt, usage; -> syscall(Syswait4, a(pid), a(loc), a(opt), a(usage))}
const waitpid = {pid, loc, opt;
var rusage
- -> wait4(pid, loc, opt, &rusage)
+ -> (wait4(pid, loc, opt, &rusage) : pid)
}
const execv = {cmd, args