Changeset 115903 in webkit
- Timestamp:
- May 2, 2012 4:05:52 PM (12 years ago)
- Location:
- trunk/Tools
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r115900 r115903 1 2012-05-02 Dirk Pranke <dpranke@chromium.org> 2 3 nrwt: make ServerProcess work on chromium win 4 https://bugs.webkit.org/show_bug.cgi?id=85333 5 6 Reviewed by Ojan Vafai. 7 8 This change implements a poor man's select() that will 9 slow-spin doing non-blocking reads on the stdout and stderr 10 named pipes connecting the worker to the driver. Seems to work 11 and I have yet to see much overhead or ill effects but it 12 probably needs more testing. 13 14 * Scripts/webkitpy/layout_tests/port/chromium.py: 15 (ChromiumDriver.__init__): 16 * Scripts/webkitpy/layout_tests/port/server_process.py: 17 (ServerProcess._start): 18 (ServerProcess._wait_for_data_and_update_buffers_using_select): 19 (ServerProcess._wait_for_data_and_update_buffers_using_win32_apis): 20 (ServerProcess): 21 (ServerProcess._non_blocking_read_win32): 22 (ServerProcess._read): 23 * Scripts/webkitpy/layout_tests/port/server_process_unittest.py: 24 (TestServerProcess.test_basic): Added. 25 1 26 2012-05-02 Raphael Kubo da Costa <rakuco@webkit.org> 2 27 -
trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
r115490 r115903 413 413 self._image_path = None 414 414 415 # FIXME: Make the regular webkit driver work on win as well so we can delete all of this driver code. 416 if port.host.platform.is_win(): 417 if not hasattr(port._options, 'additional_drt_flag'): 418 port._options.additional_drt_flag = [] 419 if not '--test-shell' in port._options.additional_drt_flag: 420 port._options.additional_drt_flag.append('--test-shell') 421 415 # FIXME: Delete all of this driver code once we're satisfied that it's not needed any more. 422 416 self._test_shell = '--test-shell' in port.get_option('additional_drt_flag', []) 423 417 -
trunk/Tools/Scripts/webkitpy/layout_tests/port/server_process.py
r115377 r115903 31 31 32 32 import logging 33 import os34 import select35 33 import signal 36 34 import subprocess 37 35 import sys 38 36 import time 39 if sys.platform != 'win32': 37 38 # Note that although win32 python does provide an implementation of 39 # the win32 select API, it only works on sockets, and not on the named pipes 40 # used by subprocess, so we have to use the native APIs directly. 41 if sys.platform == 'win32': 42 import errno 43 import msvcrt 44 import win32pipe 45 import win32file 46 else: 40 47 import fcntl 48 import os 49 import select 41 50 42 51 from webkitpy.common.system.executive import Executive, ScriptError … … 46 55 47 56 48 class ServerProcess :57 class ServerProcess(object): 49 58 """This class provides a wrapper around a subprocess that 50 59 implements a simple request/response usage model. The primary benefit … … 60 69 self._reset() 61 70 self._executive = executive 71 72 # See comment in imports for why we need the win32 APIs and can't just use select. 73 # FIXME: there should be a way to get win32 vs. cygwin from platforminfo. 74 self._use_win32_apis = sys.platform == 'win32' 62 75 63 76 def name(self): … … 89 102 env=self._env) 90 103 fd = self._proc.stdout.fileno() 91 fl = fcntl.fcntl(fd, fcntl.F_GETFL) 92 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 93 fd = self._proc.stderr.fileno() 94 fl = fcntl.fcntl(fd, fcntl.F_GETFL) 95 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 104 if not self._use_win32_apis: 105 fl = fcntl.fcntl(fd, fcntl.F_GETFL) 106 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 107 fd = self._proc.stderr.fileno() 108 fl = fcntl.fcntl(fd, fcntl.F_GETFL) 109 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 96 110 97 111 def _handle_possible_interrupt(self): … … 196 210 return output 197 211 198 def _wait_for_data_and_update_buffers (self, deadline):212 def _wait_for_data_and_update_buffers_using_select(self, deadline): 199 213 out_fd = self._proc.stdout.fileno() 200 214 err_fd = self._proc.stderr.fileno() … … 210 224 pass 211 225 226 def _wait_for_data_and_update_buffers_using_win32_apis(self, deadline): 227 # See http://code.activestate.com/recipes/440554-module-to-allow-asynchronous-subprocess-use-on-win/ 228 # and http://docs.activestate.com/activepython/2.6/pywin32/modules.html 229 # for documentation on all of these win32-specific modules. 230 now = time.time() 231 out_fh = msvcrt.get_osfhandle(self._proc.stdout.fileno()) 232 err_fh = msvcrt.get_osfhandle(self._proc.stderr.fileno()) 233 while (self._proc.poll() is None) and (now < deadline): 234 output = self._non_blocking_read_win32(out_fh) 235 error = self._non_blocking_read_win32(err_fh) 236 if output or error: 237 if output: 238 self._output += output 239 if error: 240 self._error += error 241 return 242 time.sleep(0.01) 243 now = time.time() 244 return 245 246 def _non_blocking_read_win32(self, handle): 247 try: 248 _, avail, _ = win32pipe.PeekNamedPipe(handle, 0) 249 if avail > 0: 250 _, buf = win32file.ReadFile(handle, avail, None) 251 return buf 252 except Exception, e: 253 if e[0] not in (109, errno.ESHUTDOWN): # 109 == win32 ERROR_BROKEN_PIPE 254 raise 255 return None 256 212 257 def has_crashed(self): 213 258 if not self._crashed and self.poll(): … … 232 277 return bytes 233 278 234 self._wait_for_data_and_update_buffers(deadline) 279 if self._use_win32_apis: 280 self._wait_for_data_and_update_buffers_using_win32_apis(deadline) 281 else: 282 self._wait_for_data_and_update_buffers_using_select(deadline) 235 283 236 284 def start(self): -
trunk/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py
r115377 r115903 28 28 29 29 import sys 30 import time 30 31 import unittest 31 32 33 from webkitpy.layout_tests.port.factory import PortFactory 32 34 from webkitpy.layout_tests.port import server_process 33 35 from webkitpy.common.system.executive import ScriptError 34 36 from webkitpy.common.system.executive_mock import MockExecutive2 37 from webkitpy.common.system.systemhost import SystemHost 35 38 from webkitpy.common.system.outputcapture import OutputCapture 36 39 … … 79 82 80 83 class TestServerProcess(unittest.TestCase): 84 def test_basic(self): 85 cmd = [sys.executable, '-c', 'import sys; import time; time.sleep(0.02); print "stdout"; sys.stdout.flush(); print >>sys.stderr, "stderr"'] 86 host = SystemHost() 87 factory = PortFactory(host) 88 port = factory.get() 89 now = time.time() 90 proc = server_process.ServerProcess(port, 'python', cmd) 91 proc.write('') 92 93 self.assertEquals(proc.poll(), None) 94 self.assertFalse(proc.has_crashed()) 95 96 # check that doing a read after an expired deadline returns 97 # nothing immediately. 98 line = proc.read_stdout_line(now - 1) 99 self.assertEquals(line, None) 100 101 line = proc.read_stdout_line(now + 1.0) 102 self.assertEquals(line.strip(), "stdout") 103 104 line = proc.read_stderr_line(now + 1.0) 105 self.assertEquals(line.strip(), "stderr") 106 107 proc.stop() 108 81 109 def test_broken_pipe(self): 82 110 server_process = FakeServerProcess(port_obj=TrivialMockPort(), name="test", cmd=["test"])
Note: See TracChangeset
for help on using the changeset viewer.