diff options
author | LRN <lrn1986@gmail.com> | 2013-03-31 01:23:56 +0000 |
---|---|---|
committer | LRN <lrn1986@gmail.com> | 2013-03-31 01:23:56 +0000 |
commit | 548b467c7ec7521165ff287090b14dfa8fc1b8b3 (patch) | |
tree | bc39dc73910576ead2796a5a35ad45b662fe2741 /contrib | |
parent | c6cb156eb769f8c58f4b93dcb4cc651edd35fec9 (diff) | |
download | gnunet-548b467c7ec7521165ff287090b14dfa8fc1b8b3.tar.gz gnunet-548b467c7ec7521165ff287090b14dfa8fc1b8b3.zip |
Update w32 buildslave patch to 0.8.6p1, and FINALLY FIX THE DAMN THING
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/buildslave-0.8.5-gnunet-w32.patch | 183 | ||||
-rw-r--r-- | contrib/buildslave-0.8.6p1-gnunet-w32.patch | 202 |
2 files changed, 202 insertions, 183 deletions
diff --git a/contrib/buildslave-0.8.5-gnunet-w32.patch b/contrib/buildslave-0.8.5-gnunet-w32.patch deleted file mode 100644 index 8b910fb47..000000000 --- a/contrib/buildslave-0.8.5-gnunet-w32.patch +++ /dev/null | |||
@@ -1,183 +0,0 @@ | |||
1 | diff -urN buildbot-slave-0.8.5.orig/buildslave/runprocess.py buildbot-slave-0.8.5/buildslave/runprocess.py | ||
2 | --- buildbot-slave-0.8.5.orig/buildslave/runprocess.py 2011-09-03 23:59:10 +0400 | ||
3 | +++ buildbot-slave-0.8.5/buildslave/runprocess.py 2012-11-02 03:08:05 +0400 | ||
4 | @@ -24,6 +24,7 @@ | ||
5 | import re | ||
6 | import subprocess | ||
7 | import traceback | ||
8 | +import tempfile | ||
9 | import stat | ||
10 | from collections import deque | ||
11 | |||
12 | @@ -36,6 +37,54 @@ | ||
13 | if runtime.platformType == 'posix': | ||
14 | from twisted.internet.process import Process | ||
15 | |||
16 | +if os.name == 'nt': | ||
17 | + import win32api | ||
18 | + import win32process | ||
19 | + | ||
20 | +def safe_terminate_process (proc, code): | ||
21 | + if os.name == 'nt': | ||
22 | + cp = win32api.GetCurrentProcess () | ||
23 | + result = False | ||
24 | + dupproc = win32api.DuplicateHandle (cp, proc._handle, cp, 2 | 1024 | 8 | 32 | 16, 0, 0) | ||
25 | + try: | ||
26 | + exitcode = win32process.GetExitCodeProcess (dupproc) | ||
27 | + if exitcode == 0x103: | ||
28 | + kernel32 = win32api.GetModuleHandle ("kernel32") | ||
29 | + exitprocess = win32api.GetProcAddress (kernel32, "ExitProcess") | ||
30 | + try: | ||
31 | + th, tid = win32process.CreateRemoteThread (dupproc, None, 0, exitprocess, code, 0) | ||
32 | + win32api.CloseHandle (th) | ||
33 | + except: | ||
34 | + pass | ||
35 | + result = True | ||
36 | + else: | ||
37 | + result = True | ||
38 | + # except failed to get exit code? failed to get module handle? | ||
39 | + finally: | ||
40 | + win32api.CloseHandle (dupproc) | ||
41 | + return result | ||
42 | + else: | ||
43 | + return proc.kill () | ||
44 | + | ||
45 | +class Dummy(object): | ||
46 | + def SetHandle (self, h): | ||
47 | + self._handle = h | ||
48 | + | ||
49 | +def safe_terminate_process_by_pid (proc, code): | ||
50 | + if os.name == 'nt': | ||
51 | + try: | ||
52 | + openproc = win32api.OpenProcess (2 | 1024 | 8 | 32 | 16, 0, proc) | ||
53 | + try: | ||
54 | + d = Dummy () | ||
55 | + d.SetHandle (openproc) | ||
56 | + safe_terminate_process (d, code) | ||
57 | + finally: | ||
58 | + win32api.CloseHandle (openproc) | ||
59 | + except: | ||
60 | + pass | ||
61 | + else: | ||
62 | + return os.kill (proc, code) | ||
63 | + | ||
64 | def shell_quote(cmd_list): | ||
65 | # attempt to quote cmd_list such that a shell will properly re-interpret | ||
66 | # it. The pipes module is only available on UNIX, and Windows "shell" | ||
67 | @@ -148,6 +197,7 @@ | ||
68 | self.pending_stdin = "" | ||
69 | self.stdin_finished = False | ||
70 | self.killed = False | ||
71 | + self.scriptfile = "" | ||
72 | |||
73 | def setStdin(self, data): | ||
74 | assert not self.connected | ||
75 | @@ -198,6 +248,11 @@ | ||
76 | rc = 1 | ||
77 | else: | ||
78 | rc = -1 | ||
79 | + if self.scriptfile: | ||
80 | + try: | ||
81 | + os.remove (self.scriptfile) | ||
82 | + except: | ||
83 | + pass | ||
84 | self.command.finished(sig, rc) | ||
85 | |||
86 | |||
87 | @@ -400,30 +455,52 @@ | ||
88 | |||
89 | self.pp = RunProcessPP(self) | ||
90 | |||
91 | - if type(self.command) in types.StringTypes: | ||
92 | - if runtime.platformType == 'win32': | ||
93 | - argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args | ||
94 | - if '/c' not in argv: argv += ['/c'] | ||
95 | - argv += [self.command] | ||
96 | - else: | ||
97 | - # for posix, use /bin/sh. for other non-posix, well, doesn't | ||
98 | - # hurt to try | ||
99 | - argv = ['/bin/sh', '-c', self.command] | ||
100 | - display = self.fake_command | ||
101 | - else: | ||
102 | - # On windows, CreateProcess requires an absolute path to the executable. | ||
103 | - # When we call spawnProcess below, we pass argv[0] as the executable. | ||
104 | - # So, for .exe's that we have absolute paths to, we can call directly | ||
105 | - # Otherwise, we should run under COMSPEC (usually cmd.exe) to | ||
106 | - # handle path searching, etc. | ||
107 | - if runtime.platformType == 'win32' and not \ | ||
108 | - (self.command[0].lower().endswith(".exe") and os.path.isabs(self.command[0])): | ||
109 | - argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args | ||
110 | - if '/c' not in argv: argv += ['/c'] | ||
111 | - argv += list(self.command) | ||
112 | - else: | ||
113 | - argv = self.command | ||
114 | - # Attempt to format this for use by a shell, although the process isn't perfect | ||
115 | + if type(self.command) in types.StringTypes: | ||
116 | + if runtime.platformType == 'win32': | ||
117 | + if os.environ['BUILDSLAVE_SHELL']: | ||
118 | + argv = os.environ['BUILDSLAVE_SHELL'].split() # allow %COMSPEC% to have args | ||
119 | + argv += [self.command] | ||
120 | + else: | ||
121 | + argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args | ||
122 | + if '/c' not in argv: | ||
123 | + argv += ['/c'] | ||
124 | + argv += [self.command] | ||
125 | + else: | ||
126 | + # for posix, use /bin/sh. for other non-posix, well, doesn't | ||
127 | + # hurt to try | ||
128 | + argv = ['/bin/sh', '-c', self.command] | ||
129 | + display = self.fake_command | ||
130 | + else: | ||
131 | + # On windows, CreateProcess requires an absolute path to the executable. | ||
132 | + # When we call spawnProcess below, we pass argv[0] as the executable. | ||
133 | + # So, for .exe's that we have absolute paths to, we can call directly | ||
134 | + # Otherwise, we should run under COMSPEC (usually cmd.exe) to | ||
135 | + # handle path searching, etc. | ||
136 | + if runtime.platformType == 'win32' and not \ | ||
137 | + (self.command[0].lower().endswith(".exe") and os.path.isabs(self.command[0])): | ||
138 | + if os.environ['BUILDSLAVE_SHELL']: | ||
139 | + argv = os.environ['BUILDSLAVE_SHELL'].split() | ||
140 | + # Create a temporary script file that changes current directory | ||
141 | + # and runs the command we want | ||
142 | + # It will be deleted after command is finished running (see RunProcessPP) | ||
143 | + tf, tf_name = tempfile.mkstemp () | ||
144 | + f = os.fdopen (tf, 'wb') | ||
145 | + fcontents = '#!/bin/sh\ncd {}\n{}'.format ( | ||
146 | + re.sub(r'(?<!\\) ','\\ ', self.workdir.replace('\\','/')), | ||
147 | + ' '.join (self.command)) | ||
148 | + f.write (fcontents) | ||
149 | + log.msg("Script: {}".format (fcontents)) | ||
150 | + f.close () | ||
151 | + self.pp.scriptfile = tf_name | ||
152 | + argv += [tf_name.replace('\\','/')] | ||
153 | + else: | ||
154 | + argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args | ||
155 | + if '/c' not in argv: | ||
156 | + argv += ['/c'] | ||
157 | + argv += list(self.command) | ||
158 | + else: | ||
159 | + argv = self.command | ||
160 | + # Attempt to format this for use by a shell, although the process isn't perfect | ||
161 | display = shell_quote(self.fake_command) | ||
162 | |||
163 | # $PWD usually indicates the current directory; spawnProcess may not | ||
164 | @@ -433,7 +510,7 @@ | ||
165 | self.environ['PWD'] = os.path.abspath(self.workdir) | ||
166 | |||
167 | # self.stdin is handled in RunProcessPP.connectionMade | ||
168 | - | ||
169 | + log.msg("Running {}".format (argv)) | ||
170 | log.msg(" " + display) | ||
171 | self._addToBuffers('header', display+"\n") | ||
172 | |||
173 | @@ -764,9 +841,7 @@ | ||
174 | if self.KILL == None: | ||
175 | log.msg("self.KILL==None, only pretending to kill child") | ||
176 | else: | ||
177 | - log.msg("using TASKKILL /F PID /T to kill pid %s" % self.process.pid) | ||
178 | - subprocess.check_call("TASKKILL /F /PID %s /T" % self.process.pid) | ||
179 | - log.msg("taskkill'd pid %s" % self.process.pid) | ||
180 | + safe_terminate_process_by_pid (self.process.pid, 1) | ||
181 | hit = 1 | ||
182 | |||
183 | # try signalling the process itself (works on Windows too, sorta) | ||
diff --git a/contrib/buildslave-0.8.6p1-gnunet-w32.patch b/contrib/buildslave-0.8.6p1-gnunet-w32.patch new file mode 100644 index 000000000..265db4d71 --- /dev/null +++ b/contrib/buildslave-0.8.6p1-gnunet-w32.patch | |||
@@ -0,0 +1,202 @@ | |||
1 | diff -urN /src/buildbot-slave-0.8.6p1.orig/buildslave/runprocess.py /src/buildbot-slave-0.8.6p1/buildslave/runprocess.py | ||
2 | --- buildbot-slave-0.8.6p1.orig/buildslave/runprocess.py 2012-03-26 04:09:10 +0400 | ||
3 | +++ buildbot-slave-0.8.6p1/buildslave/runprocess.py 2013-03-31 05:18:55 +0400 | ||
4 | @@ -24,6 +24,7 @@ | ||
5 | import re | ||
6 | import subprocess | ||
7 | import traceback | ||
8 | +import tempfile | ||
9 | import stat | ||
10 | from collections import deque | ||
11 | |||
12 | @@ -36,6 +37,89 @@ | ||
13 | if runtime.platformType == 'posix': | ||
14 | from twisted.internet.process import Process | ||
15 | |||
16 | +if os.name == 'nt': | ||
17 | + import win32api | ||
18 | + import win32process | ||
19 | + import win32event | ||
20 | + import pywintypes | ||
21 | + | ||
22 | +def safe_terminate_process (proc, code): | ||
23 | + if os.name == 'nt': | ||
24 | + log.msg ("Obtaining current process handle") | ||
25 | + cp = win32api.GetCurrentProcess () | ||
26 | + result = False | ||
27 | + log.msg ("Expanding target process handle permissions") | ||
28 | + dupproc = win32api.DuplicateHandle (cp, proc._handle, cp, 2 | 1024 | 8 | 32 | 16 | 0x100000, 0, 0) | ||
29 | + log.msg ("Expanded.") | ||
30 | + try: | ||
31 | + log.msg ("Checking exit code of target process") | ||
32 | + exitcode = win32process.GetExitCodeProcess (dupproc) | ||
33 | + log.msg ("Exit code is %d" % exitcode) | ||
34 | + if exitcode == 0x103: | ||
35 | + log.msg ("Opening kernel32.dll") | ||
36 | + kernel32 = win32api.GetModuleHandle ("kernel32") | ||
37 | + log.msg ("Getting ExitProcess() address") | ||
38 | + exitprocess = win32api.GetProcAddress (kernel32, "ExitProcess") | ||
39 | + try: | ||
40 | + log.msg ("Creating remote thread") | ||
41 | + th = 0 | ||
42 | + tid = 0 | ||
43 | + failed = False | ||
44 | + th, tid = win32process.CreateRemoteThread (dupproc, None, 0, exitprocess, code, 0) | ||
45 | + log.msg ("Created remote thread %d" % tid) | ||
46 | + except pywintypes.error as e: | ||
47 | + if e[0] == 5: | ||
48 | + log.msg ("Access denied. It still might die, so don't fail yet") | ||
49 | + pass | ||
50 | + else: | ||
51 | + log.msg("exception %s - %s" % (sys.exc_info()[0], sys.exc_info()[1])) | ||
52 | + failed = True | ||
53 | + except Exception as e: | ||
54 | + log.msg("exception %s - %s" % (sys.exc_info()[0], sys.exc_info()[1])) | ||
55 | + failed = True | ||
56 | + if not failed: | ||
57 | + log.msg ("Wait for 5 seconds or until it dies (usually takes around 1 microsecond)") | ||
58 | + waitresult = win32event.WaitForSingleObject (dupproc, 5) | ||
59 | + log.msg ("Result of waiting: %d" % waitresult) | ||
60 | + win32api.CloseHandle (th) | ||
61 | + if waitresult == 0: | ||
62 | + result = True | ||
63 | + else: | ||
64 | + result = True | ||
65 | + except: | ||
66 | + log.msg("exception %s - %s" % (sys.exc_info()[0], sys.exc_info()[1])) | ||
67 | + finally: | ||
68 | + win32api.CloseHandle (dupproc) | ||
69 | + return result | ||
70 | + else: | ||
71 | + return proc.kill () | ||
72 | + | ||
73 | +class Dummy(object): | ||
74 | + def SetHandle (self, h): | ||
75 | + self._handle = h | ||
76 | + | ||
77 | +def safe_terminate_process_by_pid (proc, code): | ||
78 | + if os.name == 'nt': | ||
79 | + try: | ||
80 | + log.msg("Opening process %d" % proc) | ||
81 | + openproc = win32api.OpenProcess (2 | 1024 | 8 | 32 | 16 | 0x100000, 0, proc) | ||
82 | + log.msg("Opened process %d" % proc) | ||
83 | + try: | ||
84 | + d = Dummy () | ||
85 | + d.SetHandle (openproc) | ||
86 | + log.msg("Terminating it safely") | ||
87 | + safe_terminate_process (d, code) | ||
88 | + log.msg("Finished terminating") | ||
89 | + finally: | ||
90 | + log.msg("Closing process handle") | ||
91 | + win32api.CloseHandle (openproc) | ||
92 | + except: | ||
93 | + log.msg("exception %s - %s" % (sys.exc_info()[0], sys.exc_info()[1])) | ||
94 | + pass | ||
95 | + else: | ||
96 | + return os.kill (proc, code) | ||
97 | + | ||
98 | + | ||
99 | def shell_quote(cmd_list): | ||
100 | # attempt to quote cmd_list such that a shell will properly re-interpret | ||
101 | # it. The pipes module is only available on UNIX, and Windows "shell" | ||
102 | @@ -148,6 +232,7 @@ | ||
103 | self.pending_stdin = "" | ||
104 | self.stdin_finished = False | ||
105 | self.killed = False | ||
106 | + self.scriptfile = "" | ||
107 | |||
108 | def setStdin(self, data): | ||
109 | assert not self.connected | ||
110 | @@ -198,6 +283,11 @@ | ||
111 | rc = 1 | ||
112 | else: | ||
113 | rc = -1 | ||
114 | + if self.scriptfile: | ||
115 | + try: | ||
116 | + os.remove (self.scriptfile) | ||
117 | + except: | ||
118 | + pass | ||
119 | self.command.finished(sig, rc) | ||
120 | |||
121 | |||
122 | @@ -408,9 +498,14 @@ | ||
123 | |||
124 | if type(self.command) in types.StringTypes: | ||
125 | if runtime.platformType == 'win32': | ||
126 | - argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args | ||
127 | - if '/c' not in argv: argv += ['/c'] | ||
128 | - argv += [self.command] | ||
129 | + if os.environ['BUILDSLAVE_SHELL']: | ||
130 | + argv = os.environ['BUILDSLAVE_SHELL'].split() # allow %COMSPEC% to have args | ||
131 | + argv += [self.command] | ||
132 | + else: | ||
133 | + argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args | ||
134 | + if '/c' not in argv: | ||
135 | + argv += ['/c'] | ||
136 | + argv += [self.command] | ||
137 | else: | ||
138 | # for posix, use /bin/sh. for other non-posix, well, doesn't | ||
139 | # hurt to try | ||
140 | @@ -424,9 +519,26 @@ | ||
141 | # handle path searching, etc. | ||
142 | if runtime.platformType == 'win32' and not \ | ||
143 | (self.command[0].lower().endswith(".exe") and os.path.isabs(self.command[0])): | ||
144 | - argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args | ||
145 | - if '/c' not in argv: argv += ['/c'] | ||
146 | - argv += list(self.command) | ||
147 | + if os.environ['BUILDSLAVE_SHELL']: | ||
148 | + argv = os.environ['BUILDSLAVE_SHELL'].split() | ||
149 | + # Create a temporary script file that changes current directory | ||
150 | + # and runs the command we want | ||
151 | + # It will be deleted after command is finished running (see RunProcessPP) | ||
152 | + tf, tf_name = tempfile.mkstemp () | ||
153 | + f = os.fdopen (tf, 'wb') | ||
154 | + fcontents = '#!/bin/sh\ncd {}\n{}'.format ( | ||
155 | + re.sub(r'(?<!\\) ','\\ ', self.workdir.replace('\\','/')), | ||
156 | + ' '.join (self.command)) | ||
157 | + f.write (fcontents) | ||
158 | + log.msg("Script: {}".format (fcontents)) | ||
159 | + f.close () | ||
160 | + self.pp.scriptfile = tf_name | ||
161 | + argv += [tf_name.replace('\\','/')] | ||
162 | + else: | ||
163 | + argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args | ||
164 | + if '/c' not in argv: | ||
165 | + argv += ['/c'] | ||
166 | + argv += list(self.command) | ||
167 | else: | ||
168 | argv = self.command | ||
169 | # Attempt to format this for use by a shell, although the process isn't perfect | ||
170 | @@ -439,7 +551,7 @@ | ||
171 | self.environ['PWD'] = os.path.abspath(self.workdir) | ||
172 | |||
173 | # self.stdin is handled in RunProcessPP.connectionMade | ||
174 | - | ||
175 | + log.msg("Running {}".format (argv)) | ||
176 | log.msg(" " + display) | ||
177 | self._addToBuffers('header', display+"\n") | ||
178 | |||
179 | @@ -770,9 +882,7 @@ | ||
180 | if self.interruptSignal == None: | ||
181 | log.msg("self.interruptSignal==None, only pretending to kill child") | ||
182 | else: | ||
183 | - log.msg("using TASKKILL /F PID /T to kill pid %s" % self.process.pid) | ||
184 | - subprocess.check_call("TASKKILL /F /PID %s /T" % self.process.pid) | ||
185 | - log.msg("taskkill'd pid %s" % self.process.pid) | ||
186 | + safe_terminate_process_by_pid (self.process.pid, 1) | ||
187 | hit = 1 | ||
188 | |||
189 | # try signalling the process itself (works on Windows too, sorta) | ||
190 | @@ -795,10 +905,11 @@ | ||
191 | if not hit: | ||
192 | log.msg("signalProcess/os.kill failed both times") | ||
193 | |||
194 | - if runtime.platformType == "posix": | ||
195 | + if runtime.platformType == "posix" or runtime.platformType == "win32": | ||
196 | # we only do this under posix because the win32eventreactor | ||
197 | # blocks here until the process has terminated, while closing | ||
198 | # stderr. This is weird. | ||
199 | + # LRN: Turns out, things don't work without this on W32. At all. | ||
200 | self.pp.transport.loseConnection() | ||
201 | |||
202 | if self.deferred: | ||