twister: Fix race condition in try_making_symlink

Replaces the check-then-create pattern for symlinks with
opportunistic creation. Instead of checking for existence
before creating the symlink, the code now attempts to
create it directly and gracefully handles the case
where it already exists.

Signed-off-by: Tim Pambor <tim.pambor@codewrights.de>
This commit is contained in:
Tim Pambor 2025-07-23 17:50:14 +02:00 committed by Benjamin Cabé
parent 4c1c954347
commit dff24c8c00

View File

@ -518,7 +518,11 @@ def try_making_symlink(source: str, link: str):
source (str): The path to the source file.
link (str): The path where the symbolic link should be created.
"""
if os.path.exists(link):
symlink_error = None
try:
os.symlink(source, link)
except FileExistsError:
if os.path.islink(link):
if os.readlink(link) == source:
# Link is already set up
@ -529,19 +533,24 @@ def try_making_symlink(source: str, link: str):
# File contents are the same
return
# link exists, but points to a different file, remove the link. We'll
# try to create a new one below
os.remove(link)
# Create the symlink
try:
os.symlink(source, link)
# link exists, but points to a different file. We'll create a new link
# and replace it atomically with the old one
temp_filename = f"{link}.{os.urandom(8).hex()}"
try:
os.symlink(source, temp_filename)
os.replace(temp_filename, link)
except OSError as e:
symlink_error = e
except OSError as e:
logger.error(
"Error creating symlink: %s, attempting to copy.", str(e)
)
shutil.copy(source, link)
symlink_error = e
if symlink_error:
logger.error(
"Error creating symlink: %s, attempting to copy.", str(symlink_error)
)
temp_filename = f"{link}.{os.urandom(8).hex()}"
shutil.copy(source, temp_filename)
os.replace(temp_filename, link)
def choose_gcov_tool(options, is_system_gcov):
gcov_tool = None