ref: 9cb3a0f22ac95f75e87e944b95b6c5a13a4eb729
parent: f8b121ae9b3e57bbca8304676d417f680ad26f7a
author: Ori Bernstein <ori@markovcorp.com>
date: Thu Feb 15 06:19:03 EST 2018
Be a bit better about cleaning up fds on error.
--- a/lib/std/spork.myr
+++ b/lib/std/spork.myr
@@ -33,14 +33,17 @@
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,8 +53,15 @@
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
@@ -58,18 +68,22 @@
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 @@
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 @@
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
--- a/support/syscall-gen/specials+linux-x64.frag
+++ b/support/syscall-gen/specials+linux-x64.frag
@@ -19,7 +19,7 @@
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 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