Gentoo Archives: gentoo-portage-dev

From: Brian Harring <ferringb@g.o>
To: gentoo-portage-dev@l.g.o
Subject: Re: [gentoo-portage-dev] [3/7] portage_exec cleanups
Date: Sat, 29 Oct 2005 14:23:11
Message-Id: 20051029142207.GL24883@nightcrawler
In Reply to: Re: [gentoo-portage-dev] [3/7] portage_exec cleanups by Jason Stubbs
1 On Sat, Oct 29, 2005 at 07:49:49PM +0900, Jason Stubbs wrote:
2 > This patch simplifies the moving around and closing of file descriptors when
3 > setting up the pipe. The addition of fd_unused to the parameter list is in
4 > preparation of a later patch.
5
6 > +++ portage_exec.py 2005-10-29 19:07:21.000000000 +0900
7 > - # this may look ugly, but basically it moves file descriptors around to ensure no
8 > - # handles that are needed are accidentally closed during the final dup2 calls.
9 > - trg_fd=[]
10 > - if type(fd_pipes)==types.DictType:
11 > - src_fd=[]
12 > - k=fd_pipes.keys()
13 > - k.sort()
14 > - for x in k:
15 > - trg_fd.append(x)
16 > - src_fd.append(fd_pipes[x])
17 > - for x in range(0,len(trg_fd)):
18 > - if trg_fd[x] == src_fd[x]:
19 > - continue
20 > - if trg_fd[x] in src_fd[x+1:]:
21 > - new=os.dup2(trg_fd[x],max(src_fd) + 1)
22 > - os.close(trg_fd[x])
23 > - try:
24 > - while True:
25 > - src_fd[s.index(trg_fd[x])]=new
26 > - except SystemExit, e:
27 > - raise
28 > - except:
29 > - pass
30 > - for x in range(0,len(trg_fd)):
31 > - if trg_fd[x] != src_fd[x]:
32 > - os.dup2(src_fd[x], trg_fd[x])
33 > - else:
34 > - trg_fd=[0,1,2]
35
36 Above *does* need reworking, knew that when I wrote it- but the reason
37 it's so damn ugly is to cover against dup2 calls stomping handles that
38 are needed. Must be a collect, then re-arrange algo, not single pass
39
40 fd_pipes = [1:2, 2:1]
41
42 > + for x in fd_pipes:
43 > + if x != fd_pipes[x]:
44 > + os.dup2(fd_pipes[x], x)
45 > + if fd_pipes[x] not in fd_pipes and fd_pipes[x] not in fd_unused:
46 > + fd_unused.append(fd_pipes[x])
47 > + for x in fd_unused:
48 > + os.close(x)
49
50 Replacement code will fail with the simple stdout <-> stderr switch.
51 dup2 will set the actual fd 2 handle to fd 1, but *prior* to
52 duplicating fd 2 to a throw away handle so it remains open, end result
53 is that fd 2 is now fd 1, so the 2 -> 1 move does nothing.
54
55 Code above will result in 1 == 1, 2 == 1, rather then 1 == 2, 2 == 1
56
57 Which is a regression, although existing code _probably_ won't choke
58 on it- the protection I added made it robust so that it handles the
59 corner case without tripping up any dev writing the code, rather then
60 silently tieing the fd's together.
61
62
63 fd_unused doesn't cut it either also, or at the very least introduces
64 an ass biter hidden behaviour into spawn- consider
65
66 fd_pipes={}
67
68 Previous code *would* close all fd's, and execute the process as such.
69 With fd_unused addition, it won't anymore- meaning at the very least a
70 chunk of the regen code will need updating (closes stdin last I
71 looked). Very least, all callers of spawn with fd_pipes != {0:0, 1:1,
72 2:2} need verification, since the handles they were having explicitly
73 closed prior, are now left open.
74
75 With the fd_unused route, there is no way clean way to have all fd's
76 closed. You don't know what fd's are open when you spawn (nor is
77 there any way to know, beyond testing each potential fd, or overriding
78 the file builtin); going the fd_unused route means fd's the process
79 shouldn't have access to, will have access to.
80
81 Mind you the fd_unused comments are about this patch and the one +2
82 down the set.
83
84 So... regressions, both in fd_pipes handling, and in open handles
85 leaking to the spawned processes
86
87 The original code is ugly, and knowing a bit more this time around I'd
88 write it a bit differently, that said the protections/behaviour
89 originally in it should be left- it's more robust, and is expected
90 now.
91 ~harring

Replies

Subject Author
Re: [gentoo-portage-dev] [3/7] portage_exec cleanups Jason Stubbs <jstubbs@g.o>