diff options
Diffstat (limited to 'bitbake/lib/bb/utils.py')
-rw-r--r-- | bitbake/lib/bb/utils.py | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py index f688f7dd68..c288c826c0 100644 --- a/bitbake/lib/bb/utils.py +++ b/bitbake/lib/bb/utils.py | |||
@@ -1441,29 +1441,43 @@ def profile_function(profile, function, output_fn, process=True): | |||
1441 | prof.dump_stats(output_fn) | 1441 | prof.dump_stats(output_fn) |
1442 | if process: | 1442 | if process: |
1443 | process_profilelog(output_fn) | 1443 | process_profilelog(output_fn) |
1444 | serverlog("Raw profiling information saved to %s and processed statistics to %s.processed" % (output_fn, output_fn)) | 1444 | serverlog("Raw profiling information saved to %s and processed statistics to %s.report*" % (output_fn, output_fn)) |
1445 | return ret | 1445 | return ret |
1446 | else: | 1446 | else: |
1447 | return function() | 1447 | return function() |
1448 | 1448 | ||
1449 | def process_profilelog(fn, pout = None): | 1449 | def process_profilelog(fn, fn_out = None): |
1450 | # Either call with a list of filenames and set pout or a filename and optionally pout. | 1450 | # Either call with a list of filenames and set pout or a filename and optionally pout. |
1451 | if not pout: | 1451 | import pstats |
1452 | pout = fn + '.processed' | ||
1453 | 1452 | ||
1454 | with open(pout, 'w') as pout: | 1453 | if not fn_out: |
1455 | import pstats | 1454 | fn_out = fn + '.report' |
1455 | |||
1456 | def pstatopen(): | ||
1456 | if isinstance(fn, list): | 1457 | if isinstance(fn, list): |
1457 | p = pstats.Stats(*fn, stream=pout) | 1458 | return pstats.Stats(*fn, stream=pout) |
1458 | else: | 1459 | return pstats.Stats(fn, stream=pout) |
1459 | p = pstats.Stats(fn, stream=pout) | 1460 | |
1461 | with open(fn_out + '.time', 'w') as pout: | ||
1462 | p = pstatopen() | ||
1460 | p.sort_stats('time') | 1463 | p.sort_stats('time') |
1461 | p.print_stats() | 1464 | p.print_stats() |
1465 | |||
1466 | with open(fn_out + '.time-callers', 'w') as pout: | ||
1467 | p = pstatopen() | ||
1468 | p.sort_stats('time') | ||
1462 | p.print_callers() | 1469 | p.print_callers() |
1470 | |||
1471 | with open(fn_out + '.cumulative', 'w') as pout: | ||
1472 | p = pstatopen() | ||
1463 | p.sort_stats('cumulative') | 1473 | p.sort_stats('cumulative') |
1464 | p.print_stats() | 1474 | p.print_stats() |
1465 | 1475 | ||
1466 | pout.flush() | 1476 | with open(fn_out + '.cumulative-callers', 'w') as pout: |
1477 | p = pstatopen() | ||
1478 | p.sort_stats('cumulative') | ||
1479 | p.print_callers() | ||
1480 | |||
1467 | 1481 | ||
1468 | # | 1482 | # |
1469 | # Was present to work around multiprocessing pool bugs in python < 2.7.3 | 1483 | # Was present to work around multiprocessing pool bugs in python < 2.7.3 |
@@ -2226,6 +2240,15 @@ def path_is_descendant(descendant, ancestor): | |||
2226 | 2240 | ||
2227 | return False | 2241 | return False |
2228 | 2242 | ||
2243 | # Recomputing the sets in signal.py is expensive (bitbake -pP idle) | ||
2244 | # so try and use _signal directly to avoid it | ||
2245 | valid_signals = signal.valid_signals() | ||
2246 | try: | ||
2247 | import _signal | ||
2248 | sigmask = _signal.pthread_sigmask | ||
2249 | except ImportError: | ||
2250 | sigmask = signal.pthread_sigmask | ||
2251 | |||
2229 | # If we don't have a timeout of some kind and a process/thread exits badly (for example | 2252 | # If we don't have a timeout of some kind and a process/thread exits badly (for example |
2230 | # OOM killed) and held a lock, we'd just hang in the lock futex forever. It is better | 2253 | # OOM killed) and held a lock, we'd just hang in the lock futex forever. It is better |
2231 | # we exit at some point than hang. 5 minutes with no progress means we're probably deadlocked. | 2254 | # we exit at some point than hang. 5 minutes with no progress means we're probably deadlocked. |
@@ -2235,7 +2258,7 @@ def path_is_descendant(descendant, ancestor): | |||
2235 | @contextmanager | 2258 | @contextmanager |
2236 | def lock_timeout(lock): | 2259 | def lock_timeout(lock): |
2237 | try: | 2260 | try: |
2238 | s = signal.pthread_sigmask(signal.SIG_BLOCK, signal.valid_signals()) | 2261 | s = sigmask(signal.SIG_BLOCK, valid_signals) |
2239 | held = lock.acquire(timeout=5*60) | 2262 | held = lock.acquire(timeout=5*60) |
2240 | if not held: | 2263 | if not held: |
2241 | bb.server.process.serverlog("Couldn't get the lock for 5 mins, timed out, exiting.\n%s" % traceback.format_stack()) | 2264 | bb.server.process.serverlog("Couldn't get the lock for 5 mins, timed out, exiting.\n%s" % traceback.format_stack()) |
@@ -2243,17 +2266,17 @@ def lock_timeout(lock): | |||
2243 | yield held | 2266 | yield held |
2244 | finally: | 2267 | finally: |
2245 | lock.release() | 2268 | lock.release() |
2246 | signal.pthread_sigmask(signal.SIG_SETMASK, s) | 2269 | sigmask(signal.SIG_SETMASK, s) |
2247 | 2270 | ||
2248 | # A version of lock_timeout without the check that the lock was locked and a shorter timeout | 2271 | # A version of lock_timeout without the check that the lock was locked and a shorter timeout |
2249 | @contextmanager | 2272 | @contextmanager |
2250 | def lock_timeout_nocheck(lock): | 2273 | def lock_timeout_nocheck(lock): |
2251 | l = False | 2274 | l = False |
2252 | try: | 2275 | try: |
2253 | s = signal.pthread_sigmask(signal.SIG_BLOCK, signal.valid_signals()) | 2276 | s = sigmask(signal.SIG_BLOCK, valid_signals) |
2254 | l = lock.acquire(timeout=10) | 2277 | l = lock.acquire(timeout=10) |
2255 | yield l | 2278 | yield l |
2256 | finally: | 2279 | finally: |
2257 | if l: | 2280 | if l: |
2258 | lock.release() | 2281 | lock.release() |
2259 | signal.pthread_sigmask(signal.SIG_SETMASK, s) | 2282 | sigmask(signal.SIG_SETMASK, s) |