bitbake: utils: Optimise signal/sigmask performance

Running "time bitbake -pP idle" with a valid cache shows around 800,000
calls to enum creation from python's signal.py. We don't care about this
overhead and it adversely affects cache load time quite badly.

Try and use _signal directly, falling back to signal, which avoids
this overhead we don't need and makes cache loading much faster.

(Bitbake rev: 710f98844ae30416bdf6a01b655df398b49574ec)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit ee5fce67ce35b025c68aa61e2e758903269ee346)
Signed-off-by: Chris Laplante <chris.laplante@agilent.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
This commit is contained in:
Richard Purdie 2025-07-29 16:42:25 -04:00 committed by Steve Sakoman
parent b4ecf098a6
commit c9d46475eb

View File

@ -1876,6 +1876,15 @@ def path_is_descendant(descendant, ancestor):
return False
# Recomputing the sets in signal.py is expensive (bitbake -pP idle)
# so try and use _signal directly to avoid it
valid_signals = signal.valid_signals()
try:
import _signal
sigmask = _signal.pthread_sigmask
except ImportError:
sigmask = signal.pthread_sigmask
# If we don't have a timeout of some kind and a process/thread exits badly (for example
# OOM killed) and held a lock, we'd just hang in the lock futex forever. It is better
# we exit at some point than hang. 5 minutes with no progress means we're probably deadlocked.
@ -1885,7 +1894,7 @@ def path_is_descendant(descendant, ancestor):
@contextmanager
def lock_timeout(lock):
try:
s = signal.pthread_sigmask(signal.SIG_BLOCK, signal.valid_signals())
s = sigmask(signal.SIG_BLOCK, valid_signals)
held = lock.acquire(timeout=5*60)
if not held:
bb.server.process.serverlog("Couldn't get the lock for 5 mins, timed out, exiting.\n%s" % traceback.format_stack())
@ -1893,16 +1902,16 @@ def lock_timeout(lock):
yield held
finally:
lock.release()
signal.pthread_sigmask(signal.SIG_SETMASK, s)
sigmask(signal.SIG_SETMASK, s)
# A version of lock_timeout without the check that the lock was locked and a shorter timeout
@contextmanager
def lock_timeout_nocheck(lock):
try:
s = signal.pthread_sigmask(signal.SIG_BLOCK, signal.valid_signals())
s = sigmask(signal.SIG_BLOCK, valid_signals)
l = lock.acquire(timeout=10)
yield l
finally:
if l:
lock.release()
signal.pthread_sigmask(signal.SIG_SETMASK, s)
sigmask(signal.SIG_SETMASK, s)