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

Side by Side Diff: Tools/Scripts/webkitpy/layout_tests/servers/server_base.py

Issue 413063002: add debug logging for win apache issues (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: fix accidentally dropped exception message Created 6 years, 5 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
OLDNEW
1 # Copyright (C) 2011 Google Inc. All rights reserved. 1 # Copyright (C) 2011 Google Inc. All rights reserved.
2 # 2 #
3 # Redistribution and use in source and binary forms, with or without 3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are 4 # modification, are permitted provided that the following conditions are
5 # met: 5 # met:
6 # 6 #
7 # * Redistributions of source code must retain the above copyright 7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer. 8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above 9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer 10 # copyright notice, this list of conditions and the following disclaimer
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 self._mappings = {} 69 self._mappings = {}
70 self._pid_file = None 70 self._pid_file = None
71 self._start_cmd = None 71 self._start_cmd = None
72 72
73 # Subclasses may override these fields. 73 # Subclasses may override these fields.
74 self._env = None 74 self._env = None
75 self._stdout = self._executive.PIPE 75 self._stdout = self._executive.PIPE
76 self._stderr = self._executive.PIPE 76 self._stderr = self._executive.PIPE
77 self._process = None 77 self._process = None
78 self._pid = None 78 self._pid = None
79 self._error_log = None
79 80
80 def start(self): 81 def start(self):
81 """Starts the server. It is an error to start an already started server. 82 """Starts the server. It is an error to start an already started server.
82 83
83 This method also stops any stale servers started by a previous instance. """ 84 This method also stops any stale servers started by a previous instance. """
84 assert not self._pid, '%s server is already running' % self._name 85 assert not self._pid, '%s server is already running' % self._name
85 86
86 # Stop any stale servers left over from previous instances. 87 # Stop any stale servers left over from previous instances.
87 if self._filesystem.exists(self._pid_file): 88 if self._filesystem.exists(self._pid_file):
88 try: 89 try:
89 self._pid = int(self._filesystem.read_text_file(self._pid_file)) 90 self._pid = int(self._filesystem.read_text_file(self._pid_file))
91 _log.debug('stale %s pid file, pid %d' % (self._name, self._pid) )
90 self._stop_running_server() 92 self._stop_running_server()
91 except (ValueError, UnicodeDecodeError): 93 except (ValueError, UnicodeDecodeError):
92 # These could be raised if the pid file is corrupt. 94 # These could be raised if the pid file is corrupt.
93 self._remove_pid_file() 95 self._remove_pid_file()
94 self._pid = None 96 self._pid = None
95 97
96 self._remove_stale_logs() 98 self._remove_stale_logs()
97 self._prepare_config() 99 self._prepare_config()
98 self._check_that_all_ports_are_available() 100 self._check_that_all_ports_are_available()
99 101
100 self._pid = self._spawn_process() 102 self._pid = self._spawn_process()
101 103
102 if self._wait_for_action(self._is_server_running_on_all_ports): 104 if self._wait_for_action(self._is_server_running_on_all_ports):
103 _log.debug("%s successfully started (pid = %d)" % (self._name, self. _pid)) 105 _log.debug("%s successfully started (pid = %d)" % (self._name, self. _pid))
104 else: 106 else:
107 self._dump_logs()
105 self._stop_running_server() 108 self._stop_running_server()
106 raise ServerError('Failed to start %s server' % self._name) 109 raise ServerError('Failed to start %s server' % self._name)
107 110
108 def stop(self): 111 def stop(self):
109 """Stops the server. Stopping a server that isn't started is harmless."" " 112 """Stops the server. Stopping a server that isn't started is harmless."" "
110 actual_pid = None 113 actual_pid = None
111 try: 114 try:
112 if self._filesystem.exists(self._pid_file): 115 if self._filesystem.exists(self._pid_file):
113 try: 116 try:
114 actual_pid = int(self._filesystem.read_text_file(self._pid_f ile)) 117 actual_pid = int(self._filesystem.read_text_file(self._pid_f ile))
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 self._filesystem.write_text_file(self._pid_file, str(pid)) 167 self._filesystem.write_text_file(self._pid_file, str(pid))
165 return pid 168 return pid
166 169
167 def _stop_running_server(self): 170 def _stop_running_server(self):
168 self._wait_for_action(self._check_and_kill) 171 self._wait_for_action(self._check_and_kill)
169 if self._filesystem.exists(self._pid_file): 172 if self._filesystem.exists(self._pid_file):
170 self._filesystem.remove(self._pid_file) 173 self._filesystem.remove(self._pid_file)
171 174
172 def _check_and_kill(self): 175 def _check_and_kill(self):
173 if self._executive.check_running_pid(self._pid): 176 if self._executive.check_running_pid(self._pid):
177 _log.debug('pid %d is running, killing it' % self._pid)
174 host = self._port_obj.host 178 host = self._port_obj.host
175 self._executive.kill_process(self._pid) 179 self._executive.kill_process(self._pid)
176 return False 180 return False
181 else:
182 _log.debug('pid %d is not running' % self._pid)
183
177 return True 184 return True
178 185
179 def _remove_pid_file(self): 186 def _remove_pid_file(self):
180 if self._filesystem.exists(self._pid_file): 187 if self._filesystem.exists(self._pid_file):
181 self._filesystem.remove(self._pid_file) 188 self._filesystem.remove(self._pid_file)
182 189
183 def _remove_log_files(self, folder, starts_with): 190 def _remove_log_files(self, folder, starts_with):
184 files = self._filesystem.listdir(folder) 191 files = self._filesystem.listdir(folder)
185 for file in files: 192 for file in files:
186 if file.startswith(starts_with): 193 if file.startswith(starts_with):
187 full_path = self._filesystem.join(folder, file) 194 full_path = self._filesystem.join(folder, file)
188 self._filesystem.remove(full_path) 195 self._filesystem.remove(full_path)
189 196
197 def _dump_logs(self):
eseidel 2014/07/23 23:29:23 I didn't know what "dump" meant until I read it.
Dirk Pranke 2014/07/23 23:51:00 I thought dump was fairly conventional, but maybe
198 _log.error('%s dumping logs' % self._name)
199 if self._process:
200 _log.error('%s returncode %s' % (self._name, str(self._process.retur ncode)))
201 if self._process.stderr:
202 stderr_text = self._process.stderr.read()
203 if stderr_text:
204 _log.error('%s stderr:' % self._name)
205 for line in stderr_text.splitlines():
206 _log.error(' %s' % line)
207 else:
208 _log.error('%s no stderr' % self._name)
209 else:
210 _log.error('%s no stderr handle' % self._name)
211 else:
212 _log.error('%s no process' % self._name)
213 if self._error_log:
214 error_log_text = self._filesystem.read_text_file(self._error_log)
215 if error_log_text:
216 _log.error('%s error log (%s) contents:' % (self._name, self._er ror_log))
217 for line in error_log_text.splitlines():
218 _log.error(' %s' % line)
219 else:
220 _log.error('%s error log empty' % self._name)
221 _log.error('')
222 else:
223 _log.error('%s no error log' % self._name)
224
190 def _wait_for_action(self, action, wait_secs=20.0, sleep_secs=1.0): 225 def _wait_for_action(self, action, wait_secs=20.0, sleep_secs=1.0):
191 """Repeat the action for wait_sec or until it succeeds, sleeping for sle ep_secs 226 """Repeat the action for wait_sec or until it succeeds, sleeping for sle ep_secs
192 in between each attempt. Returns whether it succeeded.""" 227 in between each attempt. Returns whether it succeeded."""
193 start_time = time.time() 228 start_time = time.time()
194 while time.time() - start_time < wait_secs: 229 while time.time() - start_time < wait_secs:
195 if action(): 230 if action():
196 return True 231 return True
197 _log.debug("Waiting for action: %s" % action) 232 _log.debug("Waiting for action: %s" % action)
198 time.sleep(sleep_secs) 233 time.sleep(sleep_secs)
199 234
200 return False 235 return False
201 236
202 def _is_server_running_on_all_ports(self): 237 def _is_server_running_on_all_ports(self):
203 """Returns whether the server is running on all the desired ports.""" 238 """Returns whether the server is running on all the desired ports."""
204 if not self._executive.check_running_pid(self._pid): 239 if not self._executive.check_running_pid(self._pid):
205 _log.debug("Server isn't running at all") 240 _log.error("Server isn't running at all")
241 self._dump_logs()
206 raise ServerError("Server exited") 242 raise ServerError("Server exited")
207 243
208 for mapping in self._mappings: 244 for mapping in self._mappings:
209 s = socket.socket() 245 s = socket.socket()
210 port = mapping['port'] 246 port = mapping['port']
211 try: 247 try:
212 s.connect(('localhost', port)) 248 s.connect(('localhost', port))
213 _log.debug("Server running on %d" % port) 249 _log.debug("Server running on %d" % port)
214 except IOError, e: 250 except IOError, e:
215 if e.errno not in (errno.ECONNREFUSED, errno.ECONNRESET): 251 if e.errno not in (errno.ECONNREFUSED, errno.ECONNRESET):
216 raise 252 raise
217 _log.debug("Server NOT running on %d: %s" % (port, e)) 253 _log.debug("Server NOT running on %d: %s" % (port, e))
218 return False 254 return False
219 finally: 255 finally:
220 s.close() 256 s.close()
221 return True 257 return True
222 258
223 def _check_that_all_ports_are_available(self): 259 def _check_that_all_ports_are_available(self):
224 for mapping in self._mappings: 260 for mapping in self._mappings:
225 s = socket.socket() 261 s = socket.socket()
226 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 262 # s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
eseidel 2014/07/23 23:29:23 Intentional? Comment?
Dirk Pranke 2014/07/23 23:51:00 Definitely intentional; see the comments in patchs
227 port = mapping['port'] 263 port = mapping['port']
228 try: 264 try:
229 s.bind(('localhost', port)) 265 s.bind(('localhost', port))
230 except IOError, e: 266 except IOError, e:
231 if e.errno in (errno.EALREADY, errno.EADDRINUSE): 267 if e.errno in (errno.EALREADY, errno.EADDRINUSE):
232 raise ServerError('Port %d is already in use.' % port) 268 raise ServerError('Port %d is already in use.' % port)
233 elif sys.platform == 'win32' and e.errno in (errno.WSAEACCES,): # pylint: disable=E1101 269 elif sys.platform == 'win32' and e.errno in (errno.WSAEACCES,): # pylint: disable=E1101
234 raise ServerError('Port %d is already in use.' % port) 270 raise ServerError('Port %d is already in use.' % port)
235 else: 271 else:
236 raise 272 raise
237 finally: 273 finally:
238 s.close() 274 s.close()
275 _log.debug('all ports are available')
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698