[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Flaw in %readfrom and %writeto



In initial.es we find these comments:

#	All that, for example, the /tmp version of %readfrom does is bind
#	the named variable (which is the first argument, var) to the name
#	of a (hopefully unique) file in /tmp.

However, the uniqueness fails in some cases, as in the following example.

; for (x=1 2 3) { cat <{echo $x} & }
15946
15947
15948
; mknod: /tmp/es._devfd0.15685: File exists
mknod: /tmp/es._devfd0.15685: File exists
2
1
3

;

The crux of the matter is, of course, the fact that we run several
commands in the background, all of which try to use the same temporary
file. The relevant code in initial.es looks like this:

fn %readfrom var input cmd {
	local ($var = /tmp/es.$var.$pid) {
		unwind-protect {
			$input > $$var
			# text of $cmd is   command file
			$cmd
		} {
			rm -f $$var
		}
	}
}

I tried replacing the assignment to $var with
	local ($var = /tmp/es.^<={%bgcount 0}^.$var.$pid)
where I also define

let (n=0) fn %bgcount {n=<={$&math $n + $1}; $&result $n}

fn %background {%bgcount 1; $&background $*}

In other words, I count up the background jobs as they are spawned and use
this to make the value of $var more unique. I have not investigated what
happens if bacground jobs themselves start background jobs, but I would
guess my scheme isn't quite robust enough for that case.

Also, this will fail if the user uses $&background directly. I think this
might be better solved by internals: A forked subshell will have a new pid
although teh value of $pid is unchanged. Maybe the real pid of the
subshell could be incorporated into the value of var?

I actually never understood why $pid does not change in a forked subshell,
but that's a different matter.

Oh, and it should be noted that the above fix will fail for most of you
because you don't have math built in. Also, of course %writeto needs
fixing too.

- Harald