blob: db68308e024abf975b2cf519bcce80d459ff3462 [file] [log] [blame]
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -04001# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Upload all debug symbols required for crash reporting purposes.
6
7This script need only be used to upload release builds symbols or to debug
8crashes on non-release builds (in which case try to only upload the symbols
Mike Frysinger02e1e072013-11-10 22:11:34 -05009for those executables involved).
10"""
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -040011
Mike Frysingera4fa1e82014-01-15 01:45:56 -050012from __future__ import print_function
13
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -040014import ctypes
Mike Frysinger02e92402013-11-22 16:22:02 -050015import functools
Mike Frysingera4fa1e82014-01-15 01:45:56 -050016import httplib
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -040017import multiprocessing
18import os
Mike Frysinger094a2172013-08-14 12:54:35 -040019import poster
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -040020import random
21import textwrap
22import tempfile
23import time
Mike Frysinger094a2172013-08-14 12:54:35 -040024import urllib2
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -040025
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -040026from chromite.lib import commandline
27from chromite.lib import cros_build_lib
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -040028from chromite.lib import parallel
David Jamesc93e6a4d2014-01-13 11:37:36 -080029from chromite.lib import retry_util
Mike Frysinger69cb41d2013-08-11 20:08:19 -040030from chromite.scripts import cros_generate_breakpad_symbols
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -040031
32
33# URLs used for uploading symbols.
34OFFICIAL_UPLOAD_URL = 'http://clients2.google.com/cr/symbol'
35STAGING_UPLOAD_URL = 'http://clients2.google.com/cr/staging_symbol'
36
37
38# The crash server rejects files that are this big.
39CRASH_SERVER_FILE_LIMIT = 350 * 1024 * 1024
40# Give ourselves a little breathing room from what the server expects.
41DEFAULT_FILE_LIMIT = CRASH_SERVER_FILE_LIMIT - (10 * 1024 * 1024)
42
43
Mike Frysingercd78a082013-06-26 17:13:04 -040044# How long to wait (in seconds) for a single upload to complete. This has
45# to allow for symbols that are up to CRASH_SERVER_FILE_LIMIT in size.
46UPLOAD_TIMEOUT = 30 * 60
47
48
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -040049# Sleep for 200ms in between uploads to avoid DoS'ing symbol server.
50DEFAULT_SLEEP_DELAY = 0.2
51
52
53# Number of seconds to wait before retrying an upload. The delay will double
54# for each subsequent retry of the same symbol file.
55INITIAL_RETRY_DELAY = 1
56
57# Allow up to 7 attempts to upload a symbol file (total delay may be
58# 1+2+4+8+16+32=63 seconds).
59MAX_RETRIES = 6
60
Mike Frysingereb753bf2013-11-22 16:05:35 -050061# Number of total errors, before uploads are no longer attempted.
62# This is used to avoid lots of errors causing unreasonable delays.
63# See the related, but independent, error values below.
64MAX_TOTAL_ERRORS_FOR_RETRY = 30
65
66# A watermark of transient errors which we allow recovery from. If we hit
67# errors infrequently, overall we're probably doing fine. For example, if
68# we have one failure every 100 passes, then we probably don't want to fail
69# right away. But if we hit a string of failures in a row, we want to abort.
70#
71# The watermark starts at 0 (and can never go below that). When this error
72# level is exceeded, we stop uploading. When a failure happens, we add the
73# fail adjustment, and when an upload succeeds, we add the pass adjustment.
74# We want to penalize failures more so that we ramp up when there is a string
75# of them, but then slowly back off as things start working.
76#
77# A quick example:
78# 0.0: Starting point.
79# 0.0: Upload works, so add -0.5, and then clamp to 0.
80# 1.0: Upload fails, so add 1.0.
81# 2.0: Upload fails, so add 1.0.
82# 1.5: Upload works, so add -0.5.
83# 1.0: Upload works, so add -0.5.
84ERROR_WATERMARK = 3.0
85ERROR_ADJUST_FAIL = 1.0
86ERROR_ADJUST_PASS = -0.5
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -040087
88
89def SymUpload(sym_file, upload_url):
Mike Frysinger094a2172013-08-14 12:54:35 -040090 """Upload a symbol file to a HTTP server
91
92 The upload is a multipart/form-data POST with the following parameters:
93 code_file: the basename of the module, e.g. "app"
94 code_identifier: the module file's identifier
95 debug_file: the basename of the debugging file, e.g. "app"
96 debug_identifier: the debug file's identifier, usually consisting of
97 the guid and age embedded in the pdb, e.g.
98 "11111111BBBB3333DDDD555555555555F"
99 version: the file version of the module, e.g. "1.2.3.4"
100 product: HTTP-friendly product name
101 os: the operating system that the module was built for
102 cpu: the CPU that the module was built for
103 symbol_file: the contents of the breakpad-format symbol file
104
105 Args:
106 sym_file: The symbol file to upload
107 upload_url: The crash URL to POST the |sym_file| to
108 """
109 sym_header = cros_generate_breakpad_symbols.ReadSymsHeader(sym_file)
110
111 fields = (
112 ('code_file', sym_header.name),
113 ('debug_file', sym_header.name),
114 ('debug_identifier', sym_header.id.replace('-', '')),
115 # Should we set these fields? They aren't critical, but it might be nice?
116 # We'd have to figure out what file this symbol is coming from and what
117 # package provides it ...
118 #('version', None),
119 #('product', 'ChromeOS'),
120 ('os', sym_header.os),
121 ('cpu', sym_header.cpu),
122 poster.encode.MultipartParam.from_file('symbol_file', sym_file),
123 )
124
125 data, headers = poster.encode.multipart_encode(fields)
126 request = urllib2.Request(upload_url, data, headers)
127 request.add_header('User-agent', 'chromite.upload_symbols')
128 urllib2.urlopen(request, timeout=UPLOAD_TIMEOUT)
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400129
130
131def TestingSymUpload(sym_file, upload_url):
132 """A stub version of SymUpload for --testing usage"""
133 cmd = ['sym_upload', sym_file, upload_url]
134 # Randomly fail 80% of the time (the retry logic makes this 80%/3 per file).
135 returncode = random.randint(1, 100) <= 80
136 cros_build_lib.Debug('would run (and return %i): %s', returncode,
Matt Tennant7feda352013-12-20 14:03:40 -0800137 cros_build_lib.CmdToStr(cmd))
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400138 if returncode:
139 output = 'Failed to send the symbol file.'
140 else:
141 output = 'Successfully sent the symbol file.'
142 result = cros_build_lib.CommandResult(cmd=cmd, error=None, output=output,
143 returncode=returncode)
144 if returncode:
Mike Frysingera4fa1e82014-01-15 01:45:56 -0500145 exceptions = (
146 httplib.BadStatusLine('[BadStatusLine] forced test fail'),
147 urllib2.HTTPError(upload_url, 400, '[HTTPError] forced test fail',
148 {}, None),
149 urllib2.URLError('[URLError] forced test fail'),
150 )
151 raise random.choice(exceptions)
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400152 else:
153 return result
154
155
Mike Frysingereb753bf2013-11-22 16:05:35 -0500156def ErrorLimitHit(num_errors, watermark_errors):
157 """See if our error limit has been hit
158
159 Args:
160 num_errors: A multiprocessing.Value of the raw number of failures.
161 watermark_errors: A multiprocessing.Value of the current rate of failures.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500162
Mike Frysingereb753bf2013-11-22 16:05:35 -0500163 Returns:
164 True if our error limits have been exceeded.
165 """
166 return ((num_errors is not None and
167 num_errors.value > MAX_TOTAL_ERRORS_FOR_RETRY) or
168 (watermark_errors is not None and
169 watermark_errors.value > ERROR_WATERMARK))
170
171
172def _UpdateCounter(counter, adj):
173 """Update |counter| by |adj|
174
175 Handle atomic updates of |counter|. Also make sure it does not
176 fall below 0.
177
178 Args:
179 counter: A multiprocessing.Value to update
180 adj: The value to add to |counter|
181 """
182 def _Update():
183 clamp = 0 if type(adj) is int else 0.0
184 counter.value = max(clamp, counter.value + adj)
185
186 if hasattr(counter, 'get_lock'):
187 with counter.get_lock():
188 _Update()
189 elif counter is not None:
190 _Update()
191
192
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400193def UploadSymbol(sym_file, upload_url, file_limit=DEFAULT_FILE_LIMIT,
Mike Frysinger02e92402013-11-22 16:22:02 -0500194 sleep=0, num_errors=None, watermark_errors=None,
195 failed_queue=None):
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400196 """Upload |sym_file| to |upload_url|
197
198 Args:
199 sym_file: The full path to the breakpad symbol to upload
200 upload_url: The crash server to upload things to
201 file_limit: The max file size of a symbol file before we try to strip it
202 sleep: Number of seconds to sleep before running
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400203 num_errors: An object to update with the error count (needs a .value member)
Mike Frysingereb753bf2013-11-22 16:05:35 -0500204 watermark_errors: An object to track current error behavior (needs a .value)
Mike Frysinger02e92402013-11-22 16:22:02 -0500205 failed_queue: When a symbol fails, add it to this queue
Mike Frysinger1a736a82013-12-12 01:50:59 -0500206
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400207 Returns:
208 The number of errors that were encountered.
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400209 """
210 if num_errors is None:
211 num_errors = ctypes.c_int()
Mike Frysingereb753bf2013-11-22 16:05:35 -0500212 if ErrorLimitHit(num_errors, watermark_errors):
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400213 # Abandon ship! It's on fire! NOoooooooooooOOOoooooo.
Mike Frysinger7f9be142014-01-15 02:16:42 -0500214 if failed_queue:
215 failed_queue.put(sym_file)
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400216 return 0
217
218 upload_file = sym_file
219
220 if sleep:
221 # Keeps us from DoS-ing the symbol server.
222 time.sleep(sleep)
223
224 cros_build_lib.Debug('uploading %s' % sym_file)
225
226 # Ideally there'd be a tempfile.SpooledNamedTemporaryFile that we could use.
227 with tempfile.NamedTemporaryFile(prefix='upload_symbols',
228 bufsize=0) as temp_sym_file:
229 if file_limit:
230 # If the symbols size is too big, strip out the call frame info. The CFI
231 # is unnecessary for 32bit x86 targets where the frame pointer is used (as
232 # all of ours have) and it accounts for over half the size of the symbols
233 # uploaded.
234 file_size = os.path.getsize(sym_file)
235 if file_size > file_limit:
236 cros_build_lib.Warning('stripping CFI from %s due to size %s > %s',
237 sym_file, file_size, file_limit)
238 temp_sym_file.writelines([x for x in open(sym_file, 'rb').readlines()
239 if not x.startswith('STACK CFI')])
240 upload_file = temp_sym_file.name
241
242 # Hopefully the crash server will let it through. But it probably won't.
243 # Not sure what the best answer is in this case.
244 file_size = os.path.getsize(upload_file)
245 if file_size > CRASH_SERVER_FILE_LIMIT:
246 cros_build_lib.PrintBuildbotStepWarnings()
Mike Frysinger02e92402013-11-22 16:22:02 -0500247 cros_build_lib.Warning('upload file %s is awfully large, risking '
248 'rejection by the symbol server (%s > %s)',
249 sym_file, file_size, CRASH_SERVER_FILE_LIMIT)
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400250
251 # Upload the symbol file.
Mike Frysingereb753bf2013-11-22 16:05:35 -0500252 success = False
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400253 try:
Mike Frysinger9adcfd22013-10-24 12:01:40 -0400254 cros_build_lib.TimedCommand(
David Jamesc93e6a4d2014-01-13 11:37:36 -0800255 retry_util.RetryException,
Mike Frysinger9adcfd22013-10-24 12:01:40 -0400256 (urllib2.HTTPError, urllib2.URLError), MAX_RETRIES, SymUpload,
257 upload_file, upload_url, sleep=INITIAL_RETRY_DELAY,
258 timed_log_msg='upload of %10i bytes took %%s: %s' %
259 (file_size, os.path.basename(sym_file)))
Mike Frysingereb753bf2013-11-22 16:05:35 -0500260 success = True
Mike Frysinger094a2172013-08-14 12:54:35 -0400261 except urllib2.HTTPError as e:
262 cros_build_lib.Warning('could not upload: %s: HTTP %s: %s',
263 os.path.basename(sym_file), e.code, e.reason)
Mike Frysingera4fa1e82014-01-15 01:45:56 -0500264 except (urllib2.URLError, httplib.HTTPException) as e:
Mike Frysingerc4ab5782013-10-02 18:14:22 -0400265 cros_build_lib.Warning('could not upload: %s: %s',
266 os.path.basename(sym_file), e)
Mike Frysingereb753bf2013-11-22 16:05:35 -0500267 finally:
268 if success:
269 _UpdateCounter(watermark_errors, ERROR_ADJUST_PASS)
270 else:
271 _UpdateCounter(num_errors, 1)
272 _UpdateCounter(watermark_errors, ERROR_ADJUST_FAIL)
Mike Frysinger02e92402013-11-22 16:22:02 -0500273 if failed_queue:
274 failed_queue.put(sym_file)
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400275
276 return num_errors.value
277
278
Mike Frysinger9b2ff5c2013-11-22 10:01:12 -0500279def SymbolFinder(paths):
280 """Locate symbol files in |paths|
281
282 Args:
283 paths: A list of input paths to walk. Files are returned w/out any checks.
284 Dirs are searched for files that end in ".sym".
Mike Frysinger1a736a82013-12-12 01:50:59 -0500285
Mike Frysinger9b2ff5c2013-11-22 10:01:12 -0500286 Returns:
287 Yield every viable sym file.
288 """
289 for p in paths:
290 if os.path.isdir(p):
291 for root, _, files in os.walk(p):
292 for f in files:
293 if f.endswith('.sym'):
294 yield os.path.join(root, f)
295 else:
296 yield p
297
298
Mike Frysinger9dcf9ae2013-08-10 15:17:09 -0400299def UploadSymbols(board=None, official=False, breakpad_dir=None,
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400300 file_limit=DEFAULT_FILE_LIMIT, sleep=DEFAULT_SLEEP_DELAY,
Mike Frysinger7f9be142014-01-15 02:16:42 -0500301 upload_count=None, sym_paths=None, failed_list=None,
302 root=None, retry=True):
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400303 """Upload all the generated symbols for |board| to the crash server
304
Mike Frysinger9dcf9ae2013-08-10 15:17:09 -0400305 You can use in a few ways:
306 * pass |board| to locate all of its symbols
307 * pass |breakpad_dir| to upload all the symbols in there
Mike Frysinger9b2ff5c2013-11-22 10:01:12 -0500308 * pass |sym_paths| to upload specific symbols (or dirs of symbols)
Mike Frysinger9dcf9ae2013-08-10 15:17:09 -0400309
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400310 Args:
311 board: The board whose symbols we wish to upload
312 official: Use the official symbol server rather than the staging one
313 breakpad_dir: The full path to the breakpad directory where symbols live
314 file_limit: The max file size of a symbol file before we try to strip it
315 sleep: How long to sleep in between uploads
316 upload_count: If set, only upload this many symbols (meant for testing)
Mike Frysinger9b2ff5c2013-11-22 10:01:12 -0500317 sym_paths: Specific symbol files (or dirs of sym files) to upload,
318 otherwise search |breakpad_dir|
Mike Frysinger7f9be142014-01-15 02:16:42 -0500319 failed_list: Write the names of all sym files we did not upload; can be a
320 filename or file-like object.
Mike Frysinger118d2502013-08-19 03:36:56 -0400321 root: The tree to prefix to |breakpad_dir| (if |breakpad_dir| is not set)
Mike Frysinger02e92402013-11-22 16:22:02 -0500322 retry: Whether we should retry failures.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500323
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400324 Returns:
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400325 The number of errors that were encountered.
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400326 """
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400327 if official:
328 upload_url = OFFICIAL_UPLOAD_URL
329 else:
330 cros_build_lib.Warning('unofficial builds upload to the staging server')
331 upload_url = STAGING_UPLOAD_URL
332
Mike Frysinger9b2ff5c2013-11-22 10:01:12 -0500333 if sym_paths:
334 cros_build_lib.Info('uploading specified symbols to %s', upload_url)
Mike Frysinger9dcf9ae2013-08-10 15:17:09 -0400335 else:
336 if breakpad_dir is None:
Mike Frysinger118d2502013-08-19 03:36:56 -0400337 breakpad_dir = os.path.join(
338 root,
339 cros_generate_breakpad_symbols.FindBreakpadDir(board).lstrip('/'))
Mike Frysinger9dcf9ae2013-08-10 15:17:09 -0400340 cros_build_lib.Info('uploading all symbols to %s from %s', upload_url,
341 breakpad_dir)
Mike Frysinger9b2ff5c2013-11-22 10:01:12 -0500342 sym_paths = [breakpad_dir]
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400343
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400344 bg_errors = multiprocessing.Value('i')
Mike Frysingereb753bf2013-11-22 16:05:35 -0500345 watermark_errors = multiprocessing.Value('f')
Mike Frysinger02e92402013-11-22 16:22:02 -0500346 failed_queue = multiprocessing.Queue()
347 uploader = functools.partial(
348 UploadSymbol, file_limit=file_limit, sleep=sleep, num_errors=bg_errors,
349 watermark_errors=watermark_errors, failed_queue=failed_queue)
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400350
Mike Frysinger02e92402013-11-22 16:22:02 -0500351 # For the first run, we collect the symbols that failed. If the
352 # overall failure rate was low, we'll retry them on the second run.
353 for retry in (retry, False):
354 # We need to limit ourselves to one upload at a time to avoid the server
355 # kicking in DoS protection. See these bugs for more details:
356 # http://crbug.com/209442
357 # http://crbug.com/212496
358 with parallel.BackgroundTaskRunner(uploader, processes=1) as queue:
359 for sym_file in SymbolFinder(sym_paths):
Mike Frysinger9b2ff5c2013-11-22 10:01:12 -0500360 if upload_count == 0:
361 break
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400362
Mike Frysinger02e92402013-11-22 16:22:02 -0500363 queue.put([sym_file, upload_url])
364
365 if upload_count is not None:
366 upload_count -= 1
367 if upload_count == 0:
368 break
369
370 # See if we need to retry, and if we haven't failed too many times already.
371 if not retry or ErrorLimitHit(bg_errors, watermark_errors):
372 break
373
374 sym_paths = []
375 while not failed_queue.empty():
376 sym_paths.append(failed_queue.get())
377 if sym_paths:
378 cros_build_lib.Warning('retrying %i symbols', len(sym_paths))
Mike Frysinger0d0f9172013-12-13 15:55:40 -0500379 if upload_count is not None:
380 upload_count += len(sym_paths)
Mike Frysinger02e92402013-11-22 16:22:02 -0500381 # Decrement the error count in case we recover in the second pass.
382 assert bg_errors.value >= len(sym_paths), 'more failed files than errors?'
383 bg_errors.value -= len(sym_paths)
384 else:
385 # No failed symbols, so just return now.
386 break
387
Mike Frysinger7f9be142014-01-15 02:16:42 -0500388 # If the user has requested it, save all the symbol files that we failed to
389 # upload to a listing file. This should help with recovery efforts later on.
390 if failed_list:
391 with cros_build_lib.Open(failed_list, 'wb+') as f:
392 while not failed_queue.empty():
393 path = failed_queue.get()
394 if breakpad_dir:
395 path = os.path.relpath(path, breakpad_dir)
396 f.write('%s\n' % path)
397
Mike Frysinger9b2ff5c2013-11-22 10:01:12 -0500398 return bg_errors.value
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400399
400
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400401def main(argv):
402 parser = commandline.ArgumentParser(description=__doc__)
403
Mike Frysinger9b2ff5c2013-11-22 10:01:12 -0500404 parser.add_argument('sym_paths', type='path', nargs='*', default=None)
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400405 parser.add_argument('--board', default=None,
406 help='board to build packages for')
407 parser.add_argument('--breakpad_root', type='path', default=None,
408 help='root directory for breakpad symbols')
409 parser.add_argument('--official_build', action='store_true', default=False,
410 help='point to official symbol server')
411 parser.add_argument('--regenerate', action='store_true', default=False,
412 help='regenerate all symbols')
413 parser.add_argument('--upload-count', type=int, default=None,
414 help='only upload # number of symbols')
415 parser.add_argument('--strip_cfi', type=int,
416 default=CRASH_SERVER_FILE_LIMIT - (10 * 1024 * 1024),
417 help='strip CFI data for files above this size')
Mike Frysinger7f9be142014-01-15 02:16:42 -0500418 parser.add_argument('--failed-list', type='path',
419 help='where to save a list of failed symbols')
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400420 parser.add_argument('--testing', action='store_true', default=False,
421 help='run in testing mode')
422 parser.add_argument('--yes', action='store_true', default=False,
423 help='answer yes to all prompts')
424
425 opts = parser.parse_args(argv)
Mike Frysinger90e49ca2014-01-14 14:42:07 -0500426 opts.Freeze()
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400427
Mike Frysinger9b2ff5c2013-11-22 10:01:12 -0500428 if opts.sym_paths:
Mike Frysinger9dcf9ae2013-08-10 15:17:09 -0400429 if opts.regenerate:
430 cros_build_lib.Die('--regenerate may not be used with specific files')
431 else:
432 if opts.board is None:
433 cros_build_lib.Die('--board is required')
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400434
435 if opts.breakpad_root and opts.regenerate:
436 cros_build_lib.Die('--regenerate may not be used with --breakpad_root')
437
438 if opts.testing:
439 # TODO(build): Kill off --testing mode once unittests are up-to-snuff.
440 cros_build_lib.Info('running in testing mode')
441 # pylint: disable=W0601,W0603
442 global INITIAL_RETRY_DELAY, SymUpload, DEFAULT_SLEEP_DELAY
443 INITIAL_RETRY_DELAY = DEFAULT_SLEEP_DELAY = 0
444 SymUpload = TestingSymUpload
445
446 if not opts.yes:
447 query = textwrap.wrap(textwrap.dedent("""
448 Uploading symbols for an entire Chromium OS build is really only
449 necessary for release builds and in a few cases for developers
450 to debug problems. It will take considerable time to run. For
451 developer debugging purposes, consider instead passing specific
452 files to upload.
453 """), 80)
454 cros_build_lib.Warning('\n%s', '\n'.join(query))
455 if not cros_build_lib.BooleanPrompt(
456 prompt='Are you sure you want to upload all build symbols',
457 default=False):
458 cros_build_lib.Die('better safe than sorry')
459
460 ret = 0
461 if opts.regenerate:
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400462 ret += cros_generate_breakpad_symbols.GenerateBreakpadSymbols(
463 opts.board, breakpad_dir=opts.breakpad_root)
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400464
465 ret += UploadSymbols(opts.board, official=opts.official_build,
466 breakpad_dir=opts.breakpad_root,
467 file_limit=opts.strip_cfi, sleep=DEFAULT_SLEEP_DELAY,
Mike Frysinger7f9be142014-01-15 02:16:42 -0500468 upload_count=opts.upload_count, sym_paths=opts.sym_paths,
469 failed_list=opts.failed_list)
Mike Frysingerd5fcb3a2013-05-30 21:10:50 -0400470 if ret:
471 cros_build_lib.Error('encountered %i problem(s)', ret)
472 # Since exit(status) gets masked, clamp it to 1 so we don't inadvertently
473 # return 0 in case we are a multiple of the mask.
474 ret = 1
475
476 return ret
Mike Frysinger094a2172013-08-14 12:54:35 -0400477
478
479# We need this to run once per process. Do it at module import time as that
480# will let us avoid doing it inline at function call time (see SymUpload) as
481# that func might be called by the multiprocessing module which means we'll
482# do the opener logic multiple times overall. Plus, if you're importing this
483# module, it's a pretty good chance that you're going to need this.
484poster.streaminghttp.register_openers()