- doxygen
[oweals/gnunet.git] / contrib / buildslave-0.8.5-gnunet-w32.patch
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 = win32process.OpenProcess (2 | 1024 | 8 | 32 | 16, 0, proc)
53 +      try:
54 +        d = Dummy ()
55 +        d.SetHandle (openproc)
56 +        safe_termiate_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:\r
116 +            if runtime.platformType  == 'win32':\r
117 +                if os.environ['BUILDSLAVE_SHELL']:\r
118 +                    argv = os.environ['BUILDSLAVE_SHELL'].split() # allow %COMSPEC% to have args\r
119 +                    argv += [self.command]\r
120 +                else:\r
121 +                    argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args\r
122 +                    if '/c' not in argv:\r
123 +                        argv += ['/c']\r
124 +                    argv += [self.command]\r
125 +            else:\r
126 +                # for posix, use /bin/sh. for other non-posix, well, doesn't\r
127 +                # hurt to try\r
128 +                argv = ['/bin/sh', '-c', self.command]\r
129 +            display = self.fake_command\r
130 +        else:\r
131 +            # On windows, CreateProcess requires an absolute path to the executable.\r
132 +            # When we call spawnProcess below, we pass argv[0] as the executable.\r
133 +            # So, for .exe's that we have absolute paths to, we can call directly\r
134 +            # Otherwise, we should run under COMSPEC (usually cmd.exe) to\r
135 +            # handle path searching, etc.\r
136 +            if runtime.platformType == 'win32' and not \\r
137 +                    (self.command[0].lower().endswith(".exe") and os.path.isabs(self.command[0])):\r
138 +                if os.environ['BUILDSLAVE_SHELL']:\r
139 +                    argv = os.environ['BUILDSLAVE_SHELL'].split()\r
140 +                    # Create a temporary script file that changes current directory\r
141 +                    # and runs the command we want\r
142 +                    # It will be deleted after command is finished running (see RunProcessPP)\r
143 +                    tf, tf_name = tempfile.mkstemp ()\r
144 +                    f = os.fdopen (tf, 'wb')\r
145 +                    fcontents = '#!/bin/sh\ncd {}\n{}'.format (\r
146 +                        re.sub(r'(?<!\\) ','\\ ', self.workdir.replace('\\','/')),\r
147 +                        ' '.join (self.command))\r
148 +                    f.write (fcontents)\r
149 +                    log.msg("Script: {}".format (fcontents))\r
150 +                    f.close ()\r
151 +                    self.pp.scriptfile = tf_name\r
152 +                    argv += [tf_name.replace('\\','/')]\r
153 +                else:\r
154 +                    argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args\r
155 +                    if '/c' not in argv:\r
156 +                      argv += ['/c']\r
157 +                    argv += list(self.command)\r
158 +            else:\r
159 +                argv = self.command\r
160 +            # Attempt to format this for use by a shell, although the process isn't perfect\r
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)