builder.py: set FD_CLOEXEC flag on $3 when running a .do file.
Otherwise it could be inherited by other jwack jobs started from the same parent process, resulting in some very-hard-to-debug race conditions, let me tell you.
This commit is contained in:
parent
8d0eba9c44
commit
135d1c161a
1 changed files with 14 additions and 2 deletions
16
builder.py
16
builder.py
|
|
@ -1,4 +1,4 @@
|
||||||
import sys, os, random
|
import sys, os, random, fcntl
|
||||||
import vars, jwack, state
|
import vars, jwack, state
|
||||||
from helpers import log, log_, debug2, err, unlink
|
from helpers import log, log_, debug2, err, unlink
|
||||||
|
|
||||||
|
|
@ -31,6 +31,14 @@ def _nice(t):
|
||||||
return os.path.normpath(os.path.join(vars.PWD, t))
|
return os.path.normpath(os.path.join(vars.PWD, t))
|
||||||
|
|
||||||
|
|
||||||
|
def _close_on_exec(fd, yes):
|
||||||
|
fl = fcntl.fcntl(fd, fcntl.F_GETFD)
|
||||||
|
fl &= ~fcntl.FD_CLOEXEC
|
||||||
|
if yes:
|
||||||
|
fl |= fcntl.FD_CLOEXEC
|
||||||
|
fcntl.fcntl(fd, fcntl.F_SETFD, fl)
|
||||||
|
|
||||||
|
|
||||||
class BuildJob:
|
class BuildJob:
|
||||||
def __init__(self, t, lock, shouldbuildfunc, donefunc):
|
def __init__(self, t, lock, shouldbuildfunc, donefunc):
|
||||||
self.t = t
|
self.t = t
|
||||||
|
|
@ -62,7 +70,9 @@ class BuildJob:
|
||||||
return self._after2(1)
|
return self._after2(1)
|
||||||
state.stamp(dofile)
|
state.stamp(dofile)
|
||||||
unlink(tmpname)
|
unlink(tmpname)
|
||||||
self.f = open(tmpname, 'w+')
|
ffd = os.open(tmpname, os.O_CREAT|os.O_RDWR|os.O_EXCL)
|
||||||
|
_close_on_exec(ffd, True)
|
||||||
|
self.f = os.fdopen(ffd, 'w+')
|
||||||
# this will run in the dofile's directory, so use only basenames here
|
# this will run in the dofile's directory, so use only basenames here
|
||||||
argv = ['sh', '-e',
|
argv = ['sh', '-e',
|
||||||
os.path.basename(dofile),
|
os.path.basename(dofile),
|
||||||
|
|
@ -87,7 +97,9 @@ class BuildJob:
|
||||||
os.chdir(dn)
|
os.chdir(dn)
|
||||||
os.dup2(self.f.fileno(), 1)
|
os.dup2(self.f.fileno(), 1)
|
||||||
os.close(self.f.fileno())
|
os.close(self.f.fileno())
|
||||||
|
_close_on_exec(1, False)
|
||||||
os.execvp(self.argv[0], self.argv)
|
os.execvp(self.argv[0], self.argv)
|
||||||
|
assert(0)
|
||||||
# returns only if there's an exception
|
# returns only if there's an exception
|
||||||
|
|
||||||
def _after(self, t, rv):
|
def _after(self, t, rv):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue