Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: third_party/twisted_8_1/twisted/internet/_dumbwin32proc_orig.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.test.test_process -*-
2 # Copyright (c) 2001-2008 Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5 """
6 http://isometric.sixsided.org/_/gates_in_the_head/
7 """
8
9 import os
10
11 # Win32 imports
12 import win32api
13 import win32con
14 import win32event
15 import win32file
16 import win32pipe
17 import win32process
18 import win32security
19
20 import pywintypes
21
22 # security attributes for pipes
23 PIPE_ATTRS_INHERITABLE = win32security.SECURITY_ATTRIBUTES()
24 PIPE_ATTRS_INHERITABLE.bInheritHandle = 1
25
26 from zope.interface import implements
27 from twisted.internet.interfaces import IProcessTransport, IConsumer, IProducer
28
29 from twisted.python.win32 import quoteArguments
30
31 from twisted.internet import error
32 from twisted.python import failure
33
34 from twisted.internet import _pollingfile
35
36 def debug(msg):
37 import sys
38 print msg
39 sys.stdout.flush()
40
41 class _Reaper(_pollingfile._PollableResource):
42
43 def __init__(self, proc):
44 self.proc = proc
45
46 def checkWork(self):
47 if win32event.WaitForSingleObject(self.proc.hProcess, 0) != win32event.W AIT_OBJECT_0:
48 return 0
49 exitCode = win32process.GetExitCodeProcess(self.proc.hProcess)
50 self.deactivate()
51 self.proc.processEnded(exitCode)
52 return 0
53
54
55 def _findShebang(filename):
56 """
57 Look for a #! line, and return the value following the #! if one exists, or
58 None if this file is not a script.
59
60 I don't know if there are any conventions for quoting in Windows shebang
61 lines, so this doesn't support any; therefore, you may not pass any
62 arguments to scripts invoked as filters. That's probably wrong, so if
63 somebody knows more about the cultural expectations on Windows, please feel
64 free to fix.
65
66 This shebang line support was added in support of the CGI tests;
67 appropriately enough, I determined that shebang lines are culturally
68 accepted in the Windows world through this page:
69
70 http://www.cgi101.com/learn/connect/winxp.html
71
72 @param filename: str representing a filename
73
74 @return: a str representing another filename.
75 """
76 f = file(filename, 'ru')
77 if f.read(2) == '#!':
78 exe = f.readline(1024).strip('\n')
79 return exe
80
81 def _invalidWin32App(pywinerr):
82 """
83 Determine if a pywintypes.error is telling us that the given process is
84 'not a valid win32 application', i.e. not a PE format executable.
85
86 @param pywinerr: a pywintypes.error instance raised by CreateProcess
87
88 @return: a boolean
89 """
90
91 # Let's do this better in the future, but I have no idea what this error
92 # is; MSDN doesn't mention it, and there is no symbolic constant in
93 # win32process module that represents 193.
94
95 return pywinerr.args[0] == 193
96
97 class Process(_pollingfile._PollingTimer):
98 """A process that integrates with the Twisted event loop.
99
100 If your subprocess is a python program, you need to:
101
102 - Run python.exe with the '-u' command line option - this turns on
103 unbuffered I/O. Buffering stdout/err/in can cause problems, see e.g.
104 http://support.microsoft.com/default.aspx?scid=kb;EN-US;q1903
105
106 - If you don't want Windows messing with data passed over
107 stdin/out/err, set the pipes to be in binary mode::
108
109 import os, sys, mscvrt
110 msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
111 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
112 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
113
114 """
115 implements(IProcessTransport, IConsumer, IProducer)
116
117 buffer = ''
118 pid = None
119
120 def __init__(self, reactor, protocol, command, args, environment, path):
121 _pollingfile._PollingTimer.__init__(self, reactor)
122 self.protocol = protocol
123
124 # security attributes for pipes
125 sAttrs = win32security.SECURITY_ATTRIBUTES()
126 sAttrs.bInheritHandle = 1
127
128 # create the pipes which will connect to the secondary process
129 self.hStdoutR, hStdoutW = win32pipe.CreatePipe(sAttrs, 0)
130 self.hStderrR, hStderrW = win32pipe.CreatePipe(sAttrs, 0)
131 hStdinR, self.hStdinW = win32pipe.CreatePipe(sAttrs, 0)
132
133 win32pipe.SetNamedPipeHandleState(self.hStdinW,
134 win32pipe.PIPE_NOWAIT,
135 None,
136 None)
137
138 # set the info structure for the new process.
139 StartupInfo = win32process.STARTUPINFO()
140 StartupInfo.hStdOutput = hStdoutW
141 StartupInfo.hStdError = hStderrW
142 StartupInfo.hStdInput = hStdinR
143 StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES
144
145 # Create new handles whose inheritance property is false
146 currentPid = win32api.GetCurrentProcess()
147
148 tmp = win32api.DuplicateHandle(currentPid, self.hStdoutR, currentPid, 0, 0,
149 win32con.DUPLICATE_SAME_ACCESS)
150 win32file.CloseHandle(self.hStdoutR)
151 self.hStdoutR = tmp
152
153 tmp = win32api.DuplicateHandle(currentPid, self.hStderrR, currentPid, 0, 0,
154 win32con.DUPLICATE_SAME_ACCESS)
155 win32file.CloseHandle(self.hStderrR)
156 self.hStderrR = tmp
157
158 tmp = win32api.DuplicateHandle(currentPid, self.hStdinW, currentPid, 0, 0,
159 win32con.DUPLICATE_SAME_ACCESS)
160 win32file.CloseHandle(self.hStdinW)
161 self.hStdinW = tmp
162
163 # Add the specified environment to the current environment - this is
164 # necessary because certain operations are only supported on Windows
165 # if certain environment variables are present.
166
167 env = os.environ.copy()
168 env.update(environment or {})
169
170 cmdline = quoteArguments(args)
171 # TODO: error detection here.
172 def doCreate():
173 self.hProcess, self.hThread, self.pid, dwTid = win32process.CreatePr ocess(
174 command, cmdline, None, None, 1, 0, env, path, StartupInfo)
175 try:
176 doCreate()
177 except pywintypes.error, pwte:
178 if not _invalidWin32App(pwte):
179 # This behavior isn't _really_ documented, but let's make it
180 # consistent with the behavior that is documented.
181 raise OSError(pwte)
182 else:
183 # look for a shebang line. Insert the original 'command'
184 # (actually a script) into the new arguments list.
185 sheb = _findShebang(command)
186 if sheb is None:
187 raise OSError(
188 "%r is neither a Windows executable, "
189 "nor a script with a shebang line" % command)
190 else:
191 args = list(args)
192 args.insert(0, command)
193 cmdline = quoteArguments(args)
194 origcmd = command
195 command = sheb
196 try:
197 # Let's try again.
198 doCreate()
199 except pywintypes.error, pwte2:
200 # d'oh, failed again!
201 if _invalidWin32App(pwte2):
202 raise OSError(
203 "%r has an invalid shebang line: "
204 "%r is not a valid executable" % (
205 origcmd, sheb))
206 raise OSError(pwte2)
207
208 win32file.CloseHandle(self.hThread)
209
210 # close handles which only the child will use
211 win32file.CloseHandle(hStderrW)
212 win32file.CloseHandle(hStdoutW)
213 win32file.CloseHandle(hStdinR)
214
215 self.closed = 0
216 self.closedNotifies = 0
217
218 # set up everything
219 self.stdout = _pollingfile._PollableReadPipe(
220 self.hStdoutR,
221 lambda data: self.protocol.childDataReceived(1, data),
222 self.outConnectionLost)
223
224 self.stderr = _pollingfile._PollableReadPipe(
225 self.hStderrR,
226 lambda data: self.protocol.childDataReceived(2, data),
227 self.errConnectionLost)
228
229 self.stdin = _pollingfile._PollableWritePipe(
230 self.hStdinW, self.inConnectionLost)
231
232 for pipewatcher in self.stdout, self.stderr, self.stdin:
233 self._addPollableResource(pipewatcher)
234
235
236 # notify protocol
237 self.protocol.makeConnection(self)
238
239 # (maybe?) a good idea in win32er, otherwise not
240 # self.reactor.addEvent(self.hProcess, self, 'inConnectionLost')
241
242
243 def signalProcess(self, signalID):
244 if self.pid is None:
245 raise error.ProcessExitedAlready()
246 if signalID in ("INT", "TERM", "KILL"):
247 win32process.TerminateProcess(self.hProcess, 1)
248
249
250 def processEnded(self, status):
251 """
252 This is called when the child terminates.
253 """
254 self.pid = None
255 if status == 0:
256 err = error.ProcessDone(status)
257 else:
258 err = error.ProcessTerminated(status)
259 self.protocol.processEnded(failure.Failure(err))
260
261
262 def write(self, data):
263 """Write data to the process' stdin."""
264 self.stdin.write(data)
265
266 def writeSequence(self, seq):
267 """Write data to the process' stdin."""
268 self.stdin.writeSequence(seq)
269
270 def closeChildFD(self, fd):
271 if fd == 0:
272 self.closeStdin()
273 elif fd == 1:
274 self.closeStdout()
275 elif fd == 2:
276 self.closeStderr()
277 else:
278 raise NotImplementedError("Only standard-IO file descriptors availab le on win32")
279
280 def closeStdin(self):
281 """Close the process' stdin.
282 """
283 self.stdin.close()
284
285 def closeStderr(self):
286 self.stderr.close()
287
288 def closeStdout(self):
289 self.stdout.close()
290
291 def loseConnection(self):
292 """Close the process' stdout, in and err."""
293 self.closeStdin()
294 self.closeStdout()
295 self.closeStderr()
296
297 def outConnectionLost(self):
298 self.protocol.childConnectionLost(1)
299 self.connectionLostNotify()
300
301 def errConnectionLost(self):
302 self.protocol.childConnectionLost(2)
303 self.connectionLostNotify()
304
305 def inConnectionLost(self):
306 self.protocol.childConnectionLost(0)
307 self.connectionLostNotify()
308
309 def connectionLostNotify(self):
310 """Will be called 3 times, by stdout/err threads and process handle."""
311 self.closedNotifies = self.closedNotifies + 1
312 if self.closedNotifies == 3:
313 self.closed = 1
314 self._addPollableResource(_Reaper(self))
315
316 # IConsumer
317 def registerProducer(self, producer, streaming):
318 self.stdin.registerProducer(producer, streaming)
319
320 def unregisterProducer(self):
321 self.stdin.unregisterProducer()
322
323 # IProducer
324 def pauseProducing(self):
325 self._pause()
326
327 def resumeProducing(self):
328 self._unpause()
329
330 def stopProducing(self):
331 self.loseConnection()
332
333
334 def __repr__(self):
335 """
336 Return a string representation of the process.
337 """
338 return "<%s pid=%s>" % (self.__class__.__name__, self.pid)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698