Skip to content

Commit 3dd9779

Browse files
author
Ayden Meng
committed
BaseTools: Cap thread count to avoid file descriptor exhaustion
When the number of build threads multiplied by per-thread file descriptor usage exceeds the system's open file descriptor limit, some threads may fail to acquire necessary resources (e.g., pipes or semaphores), leading to deadlocks or hangs during parallel builds. To prevent this situation, calculate the safety upper limit of concurrency by dividing the system's maximum file descriptor limit by 3 (An empirical value derived from balancing performance overhead against the theoretical number of file descriptors consumed per thread). The actual thread count is then clamped to this safe value. This ensures stable parallel builds even under constrained resource limits. Signed-off-by: Ayden Meng <[email protected]>
1 parent 31d5b37 commit 3dd9779

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

BaseTools/Source/Python/build/build.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,13 +838,22 @@ def StartAutoGen(self,mqueue, DataPipe,SkipAutoGen,PcdMaList,cqueue):
838838
try:
839839
if SkipAutoGen:
840840
return True,0
841+
if sys.platform == "win32":
842+
SafeThreadNumber = self.ThreadNumber
843+
else:
844+
import resource
845+
soft = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
846+
SafeThreadNumber = min(self.ThreadNumber, soft // 3)
847+
if SafeThreadNumber < self.ThreadNumber:
848+
EdkLogger.info("Thread count limited to %d to avoid file descriptor exhaustion" % SafeThreadNumber)
841849
feedback_q = mp.Queue()
842850
error_event = mp.Event()
843851
FfsCmd = DataPipe.Get("FfsCommand")
844852
if FfsCmd is None:
845853
FfsCmd = {}
846854
GlobalData.FfsCmd = FfsCmd
847-
auto_workers = [AutoGenWorkerInProcess(mqueue,DataPipe.dump_file,feedback_q,GlobalData.file_lock,cqueue,self.log_q,error_event) for _ in range(self.ThreadNumber)]
855+
856+
auto_workers = [AutoGenWorkerInProcess(mqueue,DataPipe.dump_file,feedback_q,GlobalData.file_lock,cqueue,self.log_q,error_event) for _ in range(SafeThreadNumber)]
848857
self.AutoGenMgr = AutoGenManager(auto_workers,feedback_q,error_event)
849858
self.AutoGenMgr.start()
850859
for w in auto_workers:

0 commit comments

Comments
 (0)